Amend one SMS market — compliance, documents and numbers
Supplies whatever this market is waiting on, and answers with the market as stored — the same shape GET on this path returns, so what comes back can be sent back.
A market reporting ACTION_NEEDED is fixed here, whatever it is waiting on:
| Outstanding | Send |
|---|---|
a brand or campaign value (US TEN_DLC) | compliance, as below |
| a document, in any market | a multipart file named after the document's key |
| a registration sent back for correction | compliance.brand and/or compliance.campaign — the identity is accepted even once filed, and the registration goes back for review |
| different numbers | numbers, the list the market asks for from now on |
Partial, at every level
An omitted key is left alone. An explicit null clears it. Those are different requests, so {} changes nothing and is refused rather than silently accepted, and correcting one field does not blank the others.
{ "compliance": { "brand": { "contact_phone": "+12125550123" } } }
That leaves the campaign untouched, along with every other field of the identity.
What a US TEN_DLC market holds
Two halves, both singular: brand, the identity the registration is filed against, and campaign, the programme filed against it. Each carries inherit.
| Body | Effect |
|---|---|
"brand": { … } | supplies or corrects the identity, and takes one of your own |
"brand": { "inherit": true } | runs on your organization's, giving up your own |
"brand": null | the same thing, said the short way |
"campaign": { … } | supplies or corrects the programme, and takes one of your own |
"campaign": { "inherit": true } | runs on your organization's |
| key omitted | left exactly as it is |
Nothing here creates a second anything. One identity and one campaign per market, so a write is an upsert and a replayed request lands on the row it already wrote. Sending the campaign twice does not file two registrations.
Every other market
Markets that register with no regime have neither half, so compliance is 400 there. Their compliance is documents, sent here as multipart.
Documents
Send multipart/form-data with each file named after the compliance key it satisfies — the key the market's requirements names. A file that matches no document the market asks for is 400 naming the keys that would, and a file the upload rules refuse (empty, too large, an unsupported type) is 422. compliance and numbers may ride in the same form as text parts holding their JSON.
Numbers
numbers takes the list POST /v3/channels/sms takes, for a LOCAL or TEN_DLC market, and replaces what the market asks for — send the list you want, not a difference. Numbers already assigned stay; a list that leaves one of them out is 400, because nothing here releases a number.
{ "numbers": [ { "area_code": "415", "quantity": 2 }, { "quantity": 1 } ] }
A LOCAL market is claimed from inventory at once, and whatever inventory cannot cover stays pending. A TEN_DLC market's numbers are recorded on its campaign and assigned once the carriers elect it — on the next acquisition cycle when it already has been. They need a campaign of the profile's own: one inherited from the organization is 400.
What it will refuse
A filed identity is 409. Once the registration has gone to The Campaign Registry they hold a copy, and a local change would diverge from it silently. The campaign is not frozen — omit brand and the same body is accepted. The exception is a registration sent back for correction: the identity is accepted, and a correction to either half sends the registration back for review. Refiling it with The Campaign Registry stays with Sent.
More than one campaign is 409. The schema permits several and an account built on the admin side may hold them; this surface writes one, and editing whichever sorted first would leave the others unmentioned and unedited.
Nothing is submitted to a regime here. These are the rows a submission is later assembled from, which is what lets them be corrected without waiting on something externally rejectable.
Send x-profile-id with an organization key to write one of your profiles' markets.
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PATCH "https://example.com/v3/channels/sms/US/ten_dlc" \ -H "Idempotency-Key: req_abc123_retry1" \ -H "Content-Type: application/json" \ -d '{ "sandbox": false }'{
"success": true,
"data": {
"country": "US",
"number_type": "TEN_DLC",
"sender_value": "+12125550100",
"numbers": [],
"status": "ACTIVE",
"compliance": {
"brand": {
"inherit": false,
"legal_name": "Example Retail Inc",
"entity_type": "PRIVATE_PROFIT",
"country": "US",
"website": "https://example.com",
"tax_id": "12-3456789"
},
"campaign": {
"inherit": false,
"description": "Order and delivery updates for customers who opted in at checkout.",
"message_flow": "Customers opt in at checkout by checking a consent box."
},
"documents": []
}
},
"meta": {
"request_id": "req_9F7hTr3uVy",
"timestamp": "2025-06-01T12:00:00+00:00",
"version": "v3"
}
}{
"success": false,
"data": null,
"error": {
"code": "VALIDATION_001",
"message": "Supply at least one value to change",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_9F7hTr3uVy",
"timestamp": "2025-06-01T12:00:00+00:00",
"version": "v3"
}
}{
"success": false,
"data": null,
"error": {
"code": "RESOURCE_013",
"message": "This customer does not send in US as TEN_DLC",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_9F7hTr3uVy",
"timestamp": "2025-06-01T12:00:00+00:00",
"version": "v3"
}
}{
"success": false,
"data": null,
"error": {
"code": "RESOURCE_007",
"message": "The identity for this profile has already been filed with The Campaign Registry and cannot be changed here. Contact support.",
"details": null,
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_9F7hTr3uVy",
"timestamp": "2025-06-01T12:00:00+00:00",
"version": "v3"
}
}{
"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"
}
}Add an SMS market — a country and sender type POST
Gives the customer a sender in one country — the first market it sends in, and the fifth. ## What to have in place first **Call `GET /v3/compliance/requirements?country=US&type=TEN_DLC` first.** It returns this request's body ready to fill in, plus the brand and campaign calls to make before it, in order. You never have to track forty countries' rules yourself. **A market that registers with a compliance regime needs an identity, and this call takes one.** US `TEN_DLC` registers with The Campaign Registry and files that registration against a business identity. Send it in `compliance.brand` and it is recorded here, before the registration that attaches to it — so a customer with no identity reaches a first 10DLC market in one call. `{ "inherit": true }` runs on your organization's instead. A market with neither — none stored, none sent — is `400`, because accepting it would write a channel that could never register and leave it provisioning for ever with nothing saying why. **Everything the regime wants arrives in this request's `compliance`**, as two declared objects: `brand` — the identity the registration is filed against — and `campaign`, with the use case, the consent narrative, the volume, the sample messages and the keywords. There is nothing to set up first. Nothing is submitted here either: the rows are what a submission is later assembled from, and filing is externally rejectable so it happens on its own path. A market that registers with nobody — an alphanumeric sender in most countries — needs neither, and may need documents instead. ## Sending it Takes the same fields `channels.sms` takes on `POST /v3/sender-profiles`, because it is the same work, and both run one provisioning path. `compliance` is top-level and answers for the market in this request, carrying `brand` and `campaign` where the market registers. **Accepts multipart as well as JSON**, with each file named after the compliance key it satisfies — a market that pre-registers its sender needs its documents at the same moment it needs the sender. A market the customer already holds is `409`: adding what is already there is a mistake worth reporting rather than a silent no-op. A market is a `(country, sender_type)` pair, so a **second sender type in a country you already send in is fine** — `US TOLL_FREE` alongside `US TEN_DLC` is the ordinary case. Two of the same type is not. One exception: while a market's sender type is still unassigned, adding any type to that country is `409`, because the market you have may be about to become the one you asked for. Returns **the market**, in the shape `GET` and `PATCH` on `/v3/channels/sms/{country}/{type}` use — so what this answers can be read back and written back without reshaping. Not every channel you have: adding a market cannot change an RCS agent or a WhatsApp account, and `GET /v3/channels` is the whole picture. `201` when the market is ready; `202` while a sender or a registration is still outstanding. Send `x-profile-id` with an organization key to add a market to one of your profiles.
Add a WhatsApp account POST
Connects a WhatsApp Business Account shared with us through a Multi-Partner Solution to the calling sender profile. Send `x-profile-id` for the profile the account belongs to. **Two fields, because everything else is derived.** `waba_id` says which of your organization's shared accounts this is — you hold one per client, and nothing else can say which. `phone_number_id` says which number on it to send from — an account may hold several, and choosing for you would mean deciding which of your customer's numbers their traffic leaves from. The solution the account arrived through, the client business portfolio that owns it, the access token and its expiry are all resolved from your organization. They are not accepted here: the first two are Meta's answer about provenance, and the token is minted per client business and rotates roughly every sixty days, so a value you sent would be stale before it was useful. `phone_number_id` is optional. Omit it to connect the account now and settle the number later — the channel reads as `provisioning` and the profile keeps sending from your organization's account until a number is named. The same resolution runs behind `channels.whatsapp` on `POST /v3/sender-profiles`, so connecting at create and connecting afterwards fill the same fields. Returns **the account**, not every channel you have — adding one cannot change a market or an RCS agent, and `GET /v3/channels` is the whole picture. Giving an account up is not self-service: ask support, because deregistering a number lands in your own Meta business.