Get compliance requirements for a market

Call this first. It returns what a channel, country and sender type demand before you can send there — and setup[], the calls that satisfy those demands, in order, each with a body you can copy and send as it stands. You never have to track forty countries' rules yourself.

Channel

channel is sms, whatsapp or rcs, and defaults to sms — so a caller that omits it gets exactly what this endpoint has always returned.

sms is the only one answered today; the other two are 501 until their requirements are declared. They are refused rather than answered with an empty requirement set, because empty would say the channel demands nothing, and both demand plenty — WhatsApp a business verification and a display name review, RCS a carrier approval. Saying "not yet" is the true answer and the same one POST /v3/sender-profiles gives for channels.whatsapp.

type is an SMS sender type, and SMS is the only channel whose senders have one.

Requirements vary enormously. US TEN_DLC registers a brand and a campaign with The Campaign Registry and asks for a substantial set of values. An alphanumeric sender in one country pre-registers with supporting documents; in another it needs nothing at all. This is the authoritative answer for whichever market you are asking about, and it is the same declaration used to validate the calls themselves — so it can never drift from what is actually enforced.

setup[] — what to do

One step. POST /v3/channels/sms adds the market and records everything it registers with — the identity in compliance.brand, the programme in compliance.campaign. There were three, in a load-bearing order, while the identity and the campaign were resources of their own; they are members of this call's body now, so there is nothing to sequence.

Correct any of it afterwards with PATCH /v3/channels/sms/{country}/{type}, which takes the same compliance object one key at a time.

Each step's body has every key that market wants already present, with the values left blank. Blank rather than filled with placeholders, because the body is meant to be sent: a null value counts as not supplied, so posting a step verbatim comes back naming every blank you left. attachments[] lists files to send as multipart on the channel call, each under the field name given — a file cannot be a JSON value, so documents are never listed in compliance[].

Every step is a call for whoever holds the key. To set a sender profile up instead, send the same requests with the x-profile-id header naming it; there is no separate path.

requirements[] — what each value means

Each entry names a key for the compliance array, its value type, and whether it is required. required_when marks values needed only in certain cases — evaluate it against your own payload, e.g. brand.entity_type == PUBLIC_PROFIT. options lists accepted values where the market constrains them, and label is suitable for rendering a form field.

Values Sent supplies on your behalf are never listed: correlation ids, environment flags, carrier elections, and booleans derivable from what you already send.

When nothing is required

required is false and requirements is empty, and the single setup step carries no compliance array at all. A sender_id_pattern may still be present — many markets constrain the sender string without registering anything.

GET
/v3/compliance/requirements

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X GET "https://example.com/v3/compliance/requirements"
{
  "success": true,
  "data": {
    "channel": "sms",
    "country": "US",
    "type": "TEN_DLC",
    "required": true,
    "sender_id_pattern": null,
    "requirements": [
      {
        "key": "brand",
        "type": "object",
        "format": null,
        "required": false,
        "required_when": null,
        "options": null,
        "min_length": null,
        "max_items": null,
        "item_fields": [
          {
            "key": "inherit",
            "type": "boolean",
            "format": null,
            "required": false,
            "required_when": null,
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Run on the organization's brand",
            "notes": "True to register under the parent organization's identity rather than one of this profile's own; every field below is then neither asked for nor accepted. Omitted, the brand is the organization's unless this block supplies identity fields, which says plainly enough that it wants one of its own."
          },
          {
            "key": "legal_name",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Registered legal name",
            "notes": "TCR companyName — the name on the incorporation documents, which is often not the name recipients would recognise."
          },
          {
            "key": "business_name",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Public-facing name",
            "notes": "TCR displayName — the name recipients would recognise. Named for what it holds rather than for TCR's field, which is why it is not `display_name`."
          },
          {
            "key": "tax_id",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Tax identifier",
            "notes": "TCR ein. TcrBrandSubmissionValidator refuses a submission without one, so it is wanted here rather than discovered at filing time."
          },
          {
            "key": "tax_id_type",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Kind of tax identifier",
            "notes": "Which kind of identifier `tax_id` is, e.g. us_ein. Derived onto the brand form, and not itself sent to TCR."
          },
          {
            "key": "ein_issuing_country",
            "type": "string",
            "format": "iso3166_alpha2",
            "required": false,
            "required_when": null,
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Country that issued the tax id",
            "notes": "TCR einIssuingCountry — where the tax id was issued, which is not always where the business trades. Defaults to `country` when omitted, which is right for most. Takes the code or the country spelled out, as `country` does."
          },
          {
            "key": "entity_type",
            "type": "enum",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": [
              "PRIVATE_PROFIT",
              "PUBLIC_PROFIT",
              "NON_PROFIT",
              "SOLE_PROPRIETOR",
              "GOVERNMENT"
            ],
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Entity type",
            "notes": "TCR entityType. Decides which vetting TCR applies and, for SOLE_PROPRIETOR, fixes the campaign fee regardless of volume. Also refused at submission if absent."
          },
          {
            "key": "street",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Street address",
            "notes": null
          },
          {
            "key": "city",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "City",
            "notes": null
          },
          {
            "key": "state",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "State or region",
            "notes": "TCR state. Two letters for a US registration."
          },
          {
            "key": "postal_code",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Postal code",
            "notes": null
          },
          {
            "key": "country",
            "type": "string",
            "format": "iso3166_alpha2",
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Country of registration",
            "notes": "Two letters — US. The country spelled out in full is accepted too and stored as its code, which is what a read answers with and what is filed."
          },
          {
            "key": "website",
            "type": "string",
            "format": "url",
            "required": false,
            "required_when": null,
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Website",
            "notes": "TCR website. Optional, and worth sending: carriers weigh it when vetting, so a brand that has one and omits it is vetted on less than it could be."
          },
          {
            "key": "contact_name",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Responsible contact",
            "notes": "Split into TCR's firstName/lastName on submission. BrandService refuses a blank one, so a missing name is reported here rather than thrown after the profile was written."
          },
          {
            "key": "contact_email",
            "type": "string",
            "format": "email",
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Contact email",
            "notes": "TCR email."
          },
          {
            "key": "contact_phone",
            "type": "string",
            "format": "e164",
            "required": false,
            "required_when": "compliance.brand.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Contact phone",
            "notes": "TCR sends it as both phone and mobilePhone, so it is asked for once. Named for the contact it belongs to rather than as a bare `phone` on a block that also carries an address."
          }
        ],
        "label": "Business identity",
        "notes": "The identity the registration is filed against. Omit to have none; { \"inherit\": true } to register under your organization's."
      },
      {
        "key": "campaign",
        "type": "object",
        "format": null,
        "required": false,
        "required_when": "compliance.campaign.inherit != true",
        "options": null,
        "min_length": null,
        "max_items": null,
        "item_fields": [
          {
            "key": "inherit",
            "type": "boolean",
            "format": null,
            "required": false,
            "required_when": null,
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Run on the organization's campaign",
            "notes": "True to register under the parent organization's programme rather than one of this profile's own; every field below is then neither asked for nor accepted. Owning the identity and inheriting the campaign is refused — a campaign is filed against an identity registration, and chk_tcr_inheritance forbids that pairing outright."
          },
          {
            "key": "description",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "What this programme sends",
            "notes": "TCR description: what recipients will get and why, in a sentence. The only one of these TCR takes verbatim as a description of the programme, which is why it is asked for rather than derived from the customer's name."
          },
          {
            "key": "message_flow",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": 40,
            "max_items": null,
            "item_fields": null,
            "label": "Consent narrative",
            "notes": "TCR messageFlow: how recipients opt in, in prose. Under 40 characters is refused, and carriers reject vague descriptions — say where opt-in happens, that the box is unchecked by default, and that consent is not a condition of purchase."
          },
          {
            "key": "use_cases",
            "type": "array",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": 5,
            "item_fields": [
              {
                "key": "use_case",
                "type": "enum",
                "format": null,
                "required": true,
                "required_when": null,
                "options": [
                  "MARKETING",
                  "ACCOUNT_NOTIFICATION",
                  "CUSTOMER_CARE",
                  "FRAUD_ALERT",
                  "2FA",
                  "DELIVERY_NOTIFICATION",
                  "SECURITY_ALERT",
                  "M2M",
                  "HIGHER_EDUCATION",
                  "POLLING_VOTING",
                  "PUBLIC_SERVICE_ANNOUNCEMENT"
                ],
                "min_length": null,
                "max_items": null,
                "item_fields": null,
                "label": "Use case",
                "notes": "What this entry sends. MIXED and LOW_VOLUME are refused — volume decides those."
              },
              {
                "key": "sample_messages",
                "type": "array",
                "format": null,
                "required": true,
                "required_when": null,
                "options": null,
                "min_length": null,
                "max_items": 5,
                "item_fields": null,
                "label": "Sample messages",
                "notes": "TCR sample1..sample5 for this use case. One to five, each carrying the brand name and an opt-out instruction."
              }
            ],
            "label": "Use cases",
            "notes": "What the campaign sends, and an example of each. One to five entries; how they register is decided by volume, never declared."
          },
          {
            "key": "opt_in_message",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Opt-in confirmation",
            "notes": "TCR optinMessage. Should state message frequency and that rates may apply. Its presence is what sets subscriberOptin."
          },
          {
            "key": "opt_out_message",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Opt-out confirmation",
            "notes": "TCR optoutMessage. Its presence is what sets subscriberOptout."
          },
          {
            "key": "help_message",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Help reply",
            "notes": "TCR helpMessage. Its presence is what sets subscriberHelp."
          },
          {
            "key": "opt_in_keywords",
            "type": "string",
            "format": "csv_keywords",
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Opt-in keywords",
            "notes": "TCR optinKeywords, comma separated, e.g. START,YES."
          },
          {
            "key": "opt_out_keywords",
            "type": "string",
            "format": "csv_keywords",
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Opt-out keywords",
            "notes": "TCR optoutKeywords, comma separated. STOP, END, CANCEL, UNSUBSCRIBE and QUIT are honoured regardless of what is declared."
          },
          {
            "key": "help_keywords",
            "type": "string",
            "format": "csv_keywords",
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Help keywords",
            "notes": "TCR helpKeywords, comma separated, e.g. HELP,INFO."
          },
          {
            "key": "privacy_policy_link",
            "type": "string",
            "format": "url",
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Privacy policy URL",
            "notes": "TCR privacyPolicyLink."
          },
          {
            "key": "terms_and_conditions_link",
            "type": "string",
            "format": "url",
            "required": false,
            "required_when": "compliance.campaign.inherit != true",
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Terms and conditions URL",
            "notes": "TCR termsAndConditionsLink."
          },
          {
            "key": "volume",
            "type": "string",
            "format": null,
            "required": false,
            "required_when": null,
            "options": null,
            "min_length": null,
            "max_items": null,
            "item_fields": null,
            "label": "Expected monthly volume",
            "notes": "Decides how the campaign registers and which fee tier applies: below the low-volume threshold it registers as LOW_VOLUME with sub-use-cases, above it as a single use case or MIXED. Omitting it registers the campaign at the higher-fee standard tier."
          }
        ],
        "label": "Messaging campaign",
        "notes": "What the programme sends and how recipients consented. Omit to run on your organization's; supplying it takes one of your own. { \"inherit\": true } says so outright."
      }
    ],
    "setup": [
      {
        "step": 1,
        "resource": "channel",
        "method": "POST",
        "path": "/v3/channels/sms",
        "why": "Adds the market, claims a number for it, and records everything The Campaign Registry asks — the identity in `compliance.brand`, the programme in `compliance.campaign`. The registration stays outstanding until it is filed and answered, which happens off this call.",
        "body": {
          "country": "US",
          "number_type": "TEN_DLC",
          "sender_value": null,
          "compliance": {
            "brand": {
              "inherit": null,
              "legal_name": null,
              "business_name": null,
              "tax_id": null,
              "tax_id_type": null,
              "ein_issuing_country": null,
              "entity_type": null,
              "street": null,
              "city": null,
              "state": null,
              "postal_code": null,
              "country": null,
              "website": null,
              "contact_name": null,
              "contact_email": null,
              "contact_phone": null
            },
            "campaign": {
              "inherit": null,
              "description": null,
              "message_flow": null,
              "use_cases": null,
              "opt_in_message": null,
              "opt_out_message": null,
              "help_message": null,
              "opt_in_keywords": null,
              "opt_out_keywords": null,
              "help_keywords": null,
              "privacy_policy_link": null,
              "terms_and_conditions_link": null,
              "volume": null
            }
          }
        },
        "attachments": null
      }
    ]
  },
  "error": null,
  "meta": {
    "request_id": "req_7X9zKp2jDw",
    "timestamp": "2026-10-09T15:13:43.7352283+00:00",
    "version": "v3"
  }
}
{
  "success": false,
  "data": null,
  "error": {
    "code": "VALIDATION_001",
    "message": "type must be one of: LOCAL, MOBILE, TEN_DLC, TOLL_FREE, SHORT_CODE, ALPHANUMERIC",
    "details": null,
    "doc_url": "https://docs.sent.dm/reference/api/error-catalog"
  },
  "meta": {
    "request_id": "req_7X9zKp2jDw",
    "timestamp": "2026-10-09T15:13:43.7352322+00:00",
    "version": "v3"
  }
}
Empty
Empty
{
  "success": true,
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}
{
  "success": true,
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}
{
  "success": true,
  "error": {
    "code": "string",
    "message": "string",
    "details": {
      "property1": [
        "string"
      ],
      "property2": [
        "string"
      ]
    },
    "doc_url": "string"
  },
  "meta": {
    "request_id": "string",
    "timestamp": "2019-08-24T14:15:22Z",
    "version": "string"
  }
}