> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshoot India DLT gate 422 rejects (dlt_template_id)

> Unstick a 422 MESSAGING_IN_DLT_TEMPLATE_REQUIRED or MESSAGING_IN_DLT_CONTENT_MISMATCH rejection on India-bound A2P SMS — supply the DLT-approved template id, match the registered content, or scope the gate.

# Troubleshoot India DLT gate 422 rejects

India's TRAI DLT (Distributed Ledger Technology) regime routes every A2P
SMS through pre-registered content templates. Orbit's India DLT gates run
**before the send is submitted** and reject a violation with
`422 MESSAGING_IN_DLT_TEMPLATE_REQUIRED` (no template id at all) or
`422 MESSAGING_IN_DLT_CONTENT_MISMATCH` (template id present, but the
body or sender does not match your registered template). Read the code
out of the response before retrying — a blind retry re-burns the same
reject.

The gates are **tenant-owned controls**: they run only on India-bound
destinations and only when your organization has opted in via the
regional send-gates toggle (see \[Gate scope]\(#gate-scope-the-toggle-and-
environments)). Enabling them moves the reject from the carrier's DLR
back to your API response — carriers drop unregistered or mismatched
traffic at the DLT scrubbing function either way, and a carrier drop
still charges your wallet.

## Symptom: a 422 on an India-bound send

A send to an Indian destination (`+91…`) returns HTTP 422 with one of:

```json theme={null}
{
  "error": {
    "code": "MESSAGING_IN_DLT_TEMPLATE_REQUIRED",
    "status": 422,
    "message": "destination_country_IN_requires_dlt_template_id",
    "details": {
      "destination_country": "IN",
      "regulation": "TRAI_DLT",
      "hint": "Pass metadata.dlt_template_id (your DLT-approved template id) on the send."
    }
  }
}
```

or:

```json theme={null}
{
  "error": {
    "code": "MESSAGING_IN_DLT_CONTENT_MISMATCH",
    "status": 422,
    "message": "destination_country_IN_dlt_body_template_mismatch",
    "details": {
      "destination_country": "IN",
      "regulation": "TRAI_DLT",
      "dlt_template_id": "1207162159212345678",
      "mismatch_type": "body"
    }
  }
}
```

The first code means the request carried **no template id**. The second
means the request carried one, but the message body or sender does not
match the content template that id was recorded under. The fix differs —
read `details.mismatch_type` (`body` or `sender_header`) before you
retry.

## Field rules: the template id is required on every India send

India gates expect a DLT template id on **every** India-bound send.
Supply it in either shape — the gate accepts both:

```json theme={null}
{ "metadata": { "dlt_template_id": "1207162159212345678" } }
```

or nested:

```json theme={null}
{ "metadata": { "dlt": { "template_id": "1207162159212345678" } } }
```

A missing, empty, or whitespace-only value trips
`MESSAGING_IN_DLT_TEMPLATE_REQUIRED`. A non-empty string passes the
presence gate; the content match runs only when you have also recorded
that template id locally as an approved content template (next
section).

Full send examples are on [SMS channel](/channels/sms); the `metadata`
field rides in the same request as `to`, `from`, and `body`.

## Content mismatch: body and sender must match the registered template

Once a template id is recorded in your tenant's DLT registry with
`approved` status, second-layer enforcement compares the full send
against the recorded template:

| `details.mismatch_type` | Why it fired                                                                                                                                    | Fix                                                                                                                |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `body`                  | Your text does not match the registered content template — only `{#var#}` placeholders registered as variables may vary                         | Send the exact fixed text of the registered template, filling variables, or approve a new template version (below) |
| `sender_header`         | You sent from a header (Sender ID) other than the one the template was registered under — `details.registered_header` names the recorded header | Send from the recorded header, or re-record the template under the header you send from                            |

Match is anchored and case-insensitive: extra leading or trailing
content fails, but whitespace drift (newlines, double spaces) is
normalized on both sides, so formatting differences between compose
surfaces do not read as a mismatch.

### Approving a new template version

If the new wording is genuinely what you want to send, do not fight the
gate around it — secure the new content through your DLT registrar's
portal, then record the approved version in your tenant's DLT registry
via the [DLT-India registration endpoints](/compliance/dlt-india)
(content templates; the template id updates on the send). Sends with the
new id pass as soon as the recorded row reaches `approved` status.

The gate fails open when it cannot match locally: a template id with no
approved record in your tenant (registered out-of-band with the
registrar), or a tenant whose DLT tables are not yet provisioned, passes
on the id-presence check alone.

## Where to find your approved template id

Your approved template id comes from the DLT registrar's portal you
registered on. Record it — together with the header (Sender ID) and the
principal entity it belongs to — in your tenant's compliance registry so
the gate can match your sends against it:

* The dashboard compliance surface: `/compliance/dlt-india`.
* The API surface: the DLT-India registration endpoints under
  `/api/v1/compliance/dlt-india` — record content templates and read
  their `approved` status before you trust the id on a send. Full
  onboarding order (principal entity, headers, content templates,
  consent templates) is in [DLT-India Onboarding](/compliance/dlt-india).

Sends against a template id we have not recorded as approved still pass
the gate (fail-open posture), but Indian carriers will drop the traffic
downstream — keep the registry current.

## Gate scope: the toggle and environments

All India gate probes guard an organization settings key:

* Path: `regional_send_gates.IN.enabled`
* Default: **off** — India-bound sends are not gate-checked until you
  opt in.

Flip the key off while you register, or scope it to your production
organization and keep a dedicated sandbox organization with the key off
so test traffic skips the gate. Flipping it off removes both the
missing-id and content-mismatch rejects; carriers still enforce DLT
downstream, so enable it back before production volume.

To stop an in-flight send loop from burning wallet on guaranteed-fail
traffic, prefer keeping the gate on and fixing the request — the gate
rejects before any wallet deduction.

## Related references

* [DLT-India Onboarding](/compliance/dlt-india) — register the four DLT
  artifacts and record approved ids.
* [Troubleshoot strict sender-ID mode rejects](/troubleshooting/strict-sender-id-invalid-destination)
  — the sibling sender-format gate; an India send must satisfy both the
  sender format rules and the DLT template checks.
* [Sender-ID registration](/compliance/sender-id-registration) — register
  the header (Sender ID) the template is tied to.
* [Error codes](/reference/error-codes) — the full send-path error table.
