TryVox

Indian DLT

Register DLT entities and templates so SMS to +91 destinations is delivered.

Indian DLT

TRAI requires every commercial SMS into India to:

  1. Be sent under a registered Sender ID (header), tied to a registered Principal Entity.
  2. Match a registered Template word-for-word — variable placeholders allowed, but the static text must be identical.

TryVox stores your DLT registration metadata so the Messaging API can validate every SMS to +91 against it before egress. Storing a record here does not register you with the DLT operator — you still need to register on Jio TrueConnect / Airtel / VI / BSNL portals first, then mirror the resulting IDs into TryVox.

Lifecycle

1. Register your Principal Entity on a DLT operator portal.
2. Get back: entity_id, sender_ids, template_ids.
3. Mirror them into TryVox via the Compliance API.
4. Send SMS via the Messaging API — sends are validated automatically.

Registrations

A registration is the entity record (Principal Entity ID + sender IDs) for a given DLT operator.

Create

POST /v1/compliance/dlt/registrations
FieldTypeRequiredDescription
entity_idstringyesPrincipal Entity ID issued by the DLT operator.
entity_namestringyesRegistered legal name.
dlt_platformstringyesjio, airtel, vi, or bsnl.
sender_idsstring[]yesApproved sender IDs (header text), e.g. ["TRYVOX", "TVXOTP"].
curl -X POST https://api.tryvox.io/v1/compliance/dlt/registrations \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": "1701000000000012345",
    "entity_name": "Tryvox Technologies Pvt Ltd",
    "dlt_platform": "jio",
    "sender_ids": ["TRYVOX", "TVXOTP"]
  }'

201 Created returns the full record:

{
  "id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
  "entity_id": "1701000000000012345",
  "entity_name": "Tryvox Technologies Pvt Ltd",
  "dlt_platform": "jio",
  "sender_ids": ["TRYVOX", "TVXOTP"],
  "status": "active",
  "created_at": "2026-04-09T10:30:00Z"
}

List

GET /v1/compliance/dlt/registrations

Returns 200 OK with an array of every registration on the tenant.

Get

GET /v1/compliance/dlt/registrations/{id}

Update

PUT /v1/compliance/dlt/registrations/{id}

PATCH-style: only the fields you submit are applied. Common: appending a new sender_id after the operator approves it.

curl -X PUT https://api.tryvox.io/v1/compliance/dlt/registrations/$REG_ID \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{"sender_ids": ["TRYVOX", "TVXOTP", "TVXALR"]}'

Delete

DELETE /v1/compliance/dlt/registrations/{id}

204 No Content. Deleting a registration also removes any templates that reference it. SMS to +91 will start failing with 403 DLT_NOT_REGISTERED until you create a fresh registration.

Templates

A template is the body text registered with the DLT operator. Outgoing messages must match it word-for-word (placeholders are wildcards).

Create

POST /v1/compliance/dlt/templates
FieldTypeRequiredDescription
registration_iduuidyesThe registration this template belongs under.
template_idstringyesTemplate ID issued by the DLT operator.
template_namestringyesYour label.
template_bodystringyesExact body text as registered. Use {#var#} placeholders for variables (matches the DLT convention).
template_typestringyestransactional, service-implicit, service-explicit, or promotional.
sender_idstringyesWhich sender ID from the registration this template uses.
curl -X POST https://api.tryvox.io/v1/compliance/dlt/templates \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "registration_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
    "template_id": "1707000000000054321",
    "template_name": "Login OTP",
    "template_body": "Your TryVox login code is {#var#}. Valid for 5 minutes. Do not share.",
    "template_type": "transactional",
    "sender_id": "TVXOTP"
  }'

201 Created:

{
  "id": "1b2c3d4e-5f60-7180-9a2b-3c4d5e6f7a8b",
  "registration_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
  "template_id": "1707000000000054321",
  "template_name": "Login OTP",
  "template_body": "Your TryVox login code is {#var#}. Valid for 5 minutes. Do not share.",
  "template_type": "transactional",
  "sender_id": "TVXOTP",
  "status": "active",
  "created_at": "2026-04-09T10:35:00Z"
}

List, Get, Update, Delete

Mirror the registration shape:

GET    /v1/compliance/dlt/templates
GET    /v1/compliance/dlt/templates/{id}
PUT    /v1/compliance/dlt/templates/{id}
DELETE /v1/compliance/dlt/templates/{id}

Update lets you change the status (e.g. to disabled if the operator pauses your template), or fix a typo in template_body after re-registering with the operator.

Validation at send time

When the Messaging API processes an SMS to a +91 number it:

  1. Looks up an active DLT registration for the tenant whose sender_ids includes the sender on the send request.
  2. Looks up an active template under that registration whose template_body (with placeholders treated as wildcards) matches the message text.
  3. If either lookup fails, the send is rejected:
{
  "error": {
    "code": "DLT_NOT_REGISTERED",
    "message": "no DLT template matches this message body for sender 'TVXOTP'",
    "details": [
      {"field": "sender_id", "reason": "not registered"}
    ]
  }
}

The validator runs synchronously before the SMS leaves TryVox — there is no surprise rejection by the operator after the API has accepted the send.

Errors

StatusCodeReason
400VALIDATION_FAILEDMissing required field, malformed JSON
401INVALID_CREDENTIALSAuth ID / Auth Token bad
404NOT_FOUNDNo registration/template with this id, or it belongs to another tenant
409DUPLICATE_ENTITY_IDAnother registration on this tenant already uses this entity_id

Notes

  • One registration per DLT operator is typical, but you can create multiples — useful if you operate under different entities for different brands.
  • Disable instead of delete when iterating templates. Deletes are irreversible; status: "disabled" keeps history while removing the template from validation.
  • Template body matching is whitespace-tolerant but case-sensitive. Newlines, tabs, and runs of spaces are normalised before comparison.

On this page