Start free

API reference

SMS

Send SMS with an Idempotency-Key, work out segments and price before sending, look up each message and read the replies (MO) your recipients sent back.

  • 6 operations
  • Base URLhttps://api.messages.ccxcompany.co
  • AuthenticationBearer with your API key

The technical text below comes from the public contract, openapi.json, in the language the contract was written in.

Lista SMS

GET/v2/sms/messages

Ordem decrescente de criação. limit default 50, teto 200.

A lista é do ambiente da credencial que lê: uma chave ccx_test_* vê os envios de sandbox e nada mais. Para ler a produção, use uma chave ccx_live_*.

Permissão: sms:read.

Parameters

FieldInTypeDescription
statusoptionalquerystringValues:queuedsendingsentdeliveredfailedundelivered
regionoptionalquerystringValues:BRINTL
contactIdoptionalquerystring
campaignIdoptionalquerystring
phoneoptionalquerystring
fromoptionalquerystring · date-time
tooptionalquerystring · date-time
limitoptionalqueryinteger
skipoptionalqueryinteger

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    itemsrequiredobject[]
    items[].idrequiredstring
    items[].statusrequiredstringValues:queuedsendingsentdeliveredfailedundelivered
    items[].envrequiredstringValues:livetest
    items[].reasonoptionalstringValues:invalid_numbercarrier_rejectedblacklistedexpiredindeterminateabandoned
    items[].routeoptionalstringValues:premiumotpla_dedicada
    items[].torequiredstring
    items[].providerrequiredstringValues:aws-snsaws-eumpontaltechccx-sandbox
    items[].encodingoptionalstringValues:GSM-7UCS-2
    items[].lengthoptionalinteger
    items[].segmentsoptionalinteger
    items[].createdAtrequiredstring · date-time
    items[].sentAtoptionalstring · date-time
    items[].deliveredAtoptionalstring · date-time
    items[].failedAtoptionalstring · date-time
    items[].providerReceiptoptionalobject
    items[].providerReceipt.idrequiredstring
    items[].providerReceipt.typerequiredstringValues:api_messageapi_fastapi_reply
    items[].providerReceipt.torequiredstring
    items[].providerReceipt.messageoptionalstring
    items[].providerReceipt.referenceoptionalstring
    items[].providerReceipt.statusrequiredstring
    items[].providerReceipt.statusDescriptionrequiredstring
    items[].providerReceipt.receivedoptionalstring
    items[].providerReceipt.bill_factoroptionalnumber
    items[].providerReceipt.account_idoptionalnumber
    items[].providerReceipt.account_referenceoptionalstring
    items[].providerReceipt.channeloptionalstring | nullValues:SMSRCSWHATSAPP
    items[].contactIdoptionalstring
    items[].campaignIdoptionalstring
    items[].metadataoptionalobjectMetadados de correlação do seu sistema (ex.: customerId, journeyId), devolvidos intactos em todo webhook desta mensagem. Até 20 chaves; chave começa por letra e usa [A-Za-z0-9_.-] (até 64); valor é texto (até 256), número ou booleano. Não envie dado pessoal aqui.
    totalrequiredinteger
    JSON
    {  "items": [    {      "id": "string",      "status": "queued",      "env": "live",      "reason": "invalid_number",      "route": "premium",      "to": "string",      "provider": "aws-sns",      "encoding": "GSM-7",      "length": 0,      "segments": 1,      "createdAt": "2026-10-16T12:00:00.000Z",      "sentAt": "2026-10-16T12:00:00.000Z",      "deliveredAt": "2026-10-16T12:00:00.000Z",      "failedAt": "2026-10-16T12:00:00.000Z",      "providerReceipt": {        "id": "string",        "type": "api_message",        "to": "string",        "message": "string",        "reference": "string",        "status": "string",        "statusDescription": "string",        "received": "string",        "bill_factor": 0,        "account_id": 0,        "account_reference": "string",        "channel": "SMS"      },      "contactId": "string",      "campaignId": "string",      "metadata": {}    }  ],  "total": 0}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl 'https://api.messages.ccxcompany.co/v2/sms/messages' \  -H "Authorization: Bearer $CCX_API_KEY"
Required fields only. Swap the sample values for your own.

Envia um SMS

POST/v2/sms/messages

Envio síncrono: a resposta chega depois de o provedor aceitar (ou recusar) a mensagem. A entrega é assíncrona e chega no seu webhook como sms.delivered / sms.failed.

`Idempotency-Key` é obrigatória. Repetir a chave com o mesmo corpo devolve a resposta original com replayed: true e não envia nada; repetir com corpo diferente é 409.

Ambiente: vem da credencial. Uma chave ccx_test_* cai no sandbox, e env: "test" sai carimbado na resposta e no webhook. Não há como pedir um ambiente pelo corpo do request.

O sandbox mente em exatamente duas coisas, e a lista é fechada:

  1. Nada chega em telefone nenhum.
  2. O envio de sandbox não conta no seu volume mensal. O preço em billing.coins é o real de agora — mesma tabela, mesma faixa do seu volume de verdade —, mas um envio de teste nunca desloca a sua faixa. Consequência: no sandbox o preço não cai por causa de outro envio de sandbox.

Fora dessas duas, o sandbox é o produto: cobra de verdade (na carteira de sandbox), mesma contagem de segmentos, mesmo status, mesmos webhooks, mesma latência.

Finais mágicos (sandbox): salvo 0114, o número escolhe o DLR e não a resposta síncrona — validação nossa é síncrona, decisão do provedor é assíncrona.

final de towebhook, ~3s depois
0005sms.delivered
0006sms.undelivered, reason: "carrier_rejected"
0008sms.failed, reason: "invalid_number"
0013sms.failed, reason: "expired"
0018sms.failed, reason: "blacklisted"
0099nenhum, nunca — para você exercitar o próprio timeout
0114nenhum: recusa síncrona, 503 SERVICE_UNAVAILABLE — o provedor ficou sem crédito, e o crédito é da CCX, não da sua carteira
qualquer outrosms.delivered

encoding/length/segments são a contagem tarifável do Anexo I (A1.3) — a mesma que a fatura usa — do texto que sai: acento fora do GSM-7 é trocado pelo equivalente antes do envio (veja POST /v2/sms/preview). Um caractere sem equivalente (emoji, por exemplo) leva a mensagem inteira para UCS-2.

Preço: billing.coins é o custo do envio, em coins (1 coin = R$ 0,0001). É a soma do preço de CADA segmento — a faixa de volume pode virar no meio da mensagem (Cl. 8.12), então não é segments × preço do primeiro.

Saldo insuficiente é 402, e route: "la_dedicada" é 412: ela é sob consulta e não tem preço de tabela (Cl. 8.7.2). Use POST /v2/sms/preview para saber o preço antes de mandar.

429 `RATE_LIMITED`: duas causas, e as duas trazem o header Retry-After em segundos.

  1. A sua conta passou do teto de SMS por segundo contratado. A recusa acontece antes do envio: nenhuma mensagem é criada.
  2. O provedor de SMS limitou o envio (o limite é da rota, não da sua conta). Esse caso responde 429 com `Retry-After` — antes saía 502 DEPENDENCY_FAILED, sem dizer quando reenviar. A mensagem fica registrada com status failed e aparece em GET /v2/sms/messages/{id}.

Nos dois casos nada foi enviado nem cobrado: espere os segundos do Retry-After e reenvie. A Idempotency-Key é liberada, então o reenvio com a mesma chave é um envio novo (não um replay). No SMPP o mesmo 429 chega como ESME_RTHROTTLED: segure e reenvie.

Opt-out: na rota premium, destinatário cujo contato pediu para não receber comunicação é recusado com 422 e meta.motivo: "opt_out" — nada é gravado nem cobrado. A rota otp é transacional e sai sempre.

Permissão: sms:send.

Request bodyapplication/json

FieldTypeDescription
torequiredstring
bodyrequiredstring
senderIdoptionalstring
routerequiredstringRota tarifária (obrigatória): premium | otp | la_dedicada. la_dedicada é sob consulta (412).Values:premiumotpla_dedicada
contactIdoptionalstring
campaignIdoptionalstring
metadataoptionalobjectMetadados de correlação do seu sistema (ex.: customerId, journeyId), devolvidos intactos em todo webhook desta mensagem. Até 20 chaves; chave começa por letra e usa [A-Za-z0-9_.-] (até 64); valor é texto (até 256), número ou booleano. Não envie dado pessoal aqui.
trackLinksoptionalbooleantrue troca cada URL do texto por um link curto e publica sms.clicked a cada clique. O texto (e os segmentos) é contado depois da troca.
Full body example
JSON
{  "to": "string",  "body": "string",  "senderId": "string",  "route": "premium",  "contactId": "string",  "campaignId": "string",  "metadata": {},  "trackLinks": true}

Responses

  • 201Default Response

    Response fields and example
    FieldTypeDescription
    idrequiredstring
    statusrequiredstringValues:queuedsendingsentdeliveredfailedundelivered
    envrequiredstringValues:livetest
    reasonoptionalstringValues:invalid_numbercarrier_rejectedblacklistedexpiredindeterminateabandoned
    routeoptionalstringValues:premiumotpla_dedicada
    torequiredstring
    providerrequiredstringValues:aws-snsaws-eumpontaltechccx-sandbox
    encodingrequiredstringValues:GSM-7UCS-2
    lengthrequiredinteger
    segmentsrequiredinteger
    createdAtrequiredstring · date-time
    sentAtoptionalstring · date-time
    deliveredAtoptionalstring · date-time
    failedAtoptionalstring · date-time
    providerReceiptoptionalobject
    providerReceipt.idrequiredstring
    providerReceipt.typerequiredstringValues:api_messageapi_fastapi_reply
    providerReceipt.torequiredstring
    providerReceipt.messageoptionalstring
    providerReceipt.referenceoptionalstring
    providerReceipt.statusrequiredstring
    providerReceipt.statusDescriptionrequiredstring
    providerReceipt.receivedoptionalstring
    providerReceipt.bill_factoroptionalnumber
    providerReceipt.account_idoptionalnumber
    providerReceipt.account_referenceoptionalstring
    providerReceipt.channeloptionalstring | nullValues:SMSRCSWHATSAPP
    contactIdoptionalstring
    campaignIdoptionalstring
    metadataoptionalobjectMetadados de correlação do seu sistema (ex.: customerId, journeyId), devolvidos intactos em todo webhook desta mensagem. Até 20 chaves; chave começa por letra e usa [A-Za-z0-9_.-] (até 64); valor é texto (até 256), número ou booleano. Não envie dado pessoal aqui.
    billingoptionalobject
    billing.coinsrequiredinteger
    replayedrequiredboolean
    JSON
    {  "id": "string",  "status": "queued",  "env": "live",  "reason": "invalid_number",  "route": "premium",  "to": "string",  "provider": "aws-sns",  "encoding": "GSM-7",  "length": 0,  "segments": 1,  "createdAt": "2026-10-16T12:00:00.000Z",  "sentAt": "2026-10-16T12:00:00.000Z",  "deliveredAt": "2026-10-16T12:00:00.000Z",  "failedAt": "2026-10-16T12:00:00.000Z",  "providerReceipt": {    "id": "string",    "type": "api_message",    "to": "string",    "message": "string",    "reference": "string",    "status": "string",    "statusDescription": "string",    "received": "string",    "bill_factor": 0,    "account_id": 0,    "account_reference": "string",    "channel": "SMS"  },  "contactId": "string",  "campaignId": "string",  "metadata": {},  "billing": {    "coins": 0  },  "replayed": true}
  • 400RFC 7807 problem details for BAD_REQUEST (400).

  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 402RFC 7807 problem details for PAYMENT_REQUIRED (402).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 409RFC 7807 problem details for CONFLICT (409).

  • 412RFC 7807 problem details for PRECONDITION_FAILED (412).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

  • 429RFC 7807 problem details for RATE_LIMITED (429).

  • 502RFC 7807 problem details for DEPENDENCY_FAILED (502).

  • 503RFC 7807 problem details for SERVICE_UNAVAILABLE (503).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl -X POST 'https://api.messages.ccxcompany.co/v2/sms/messages' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Idempotency-Key: order-4821" \  -H "Content-Type: application/json" \  -d '{    "to": "string",    "body": "string",    "route": "premium"  }'
Required fields only. Swap the sample values for your own.

Calcula segmentos e preço sem enviar

POST/v2/sms/preview

Não envia, não cobra e não conta volume — só o aceite conta (Cl. 7.2.1), então um preview não desloca a sua faixa.

body é o texto que chega ao aparelho: as rotas de SMS não entregam acento fora do GSM-7 (chegaria sem acento ou como @), então a CCX troca cada um pelo equivalente antes de enviar (ã → a, ç → c, aspas curvas → retas; é, à e ü, que o GSM-7 tem, ficam).

Se sobrar um caractere sem equivalente (emoji, por exemplo), o texto sai como veio. A troca nunca deixa a mensagem mais cara.

segments é a contagem tarifável do Anexo I (A1.3) sobre esse body, a mesma que a fatura usa: até 160 caracteres GSM-7 é 1 segmento, acima disso um a cada 152; um único caractere fora do GSM-7 leva a mensagem inteira para UCS-2, onde os limites são 70 e 67.

billing.coins é o preço no ambiente da credencial e no seu volume de agora. Sem route não há preço a aplicar e o bloco vem ausente; la_dedicada é 412.

Permissão: sms:send.

Request bodyapplication/json

FieldTypeDescription
bodyrequiredstring
routeoptionalstringValues:premiumotpla_dedicada
Full body example
JSON
{  "body": "string",  "route": "premium"}

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    bodyrequiredstring
    encodingrequiredstringValues:GSM-7UCS-2
    lengthrequiredinteger
    segmentsrequiredinteger
    billingoptionalobject
    billing.coinsrequiredinteger
    JSON
    {  "body": "string",  "encoding": "GSM-7",  "length": 0,  "segments": 1,  "billing": {    "coins": 0  }}
  • 400RFC 7807 problem details for BAD_REQUEST (400).

  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 412RFC 7807 problem details for PRECONDITION_FAILED (412).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl -X POST 'https://api.messages.ccxcompany.co/v2/sms/preview' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Content-Type: application/json" \  -d '{    "body": "string"  }'
Required fields only. Swap the sample values for your own.

Lê um SMS pelo id

GET/v2/sms/messages/{id}

O estado corrente da mensagem. Para reagir a mudanças, use o webhook — o polling aqui vê o mesmo dado mais tarde.

Permissão: sms:read.

Parameters

FieldInTypeDescription
idrequiredpathstring

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    idrequiredstring
    statusrequiredstringValues:queuedsendingsentdeliveredfailedundelivered
    envrequiredstringValues:livetest
    reasonoptionalstringValues:invalid_numbercarrier_rejectedblacklistedexpiredindeterminateabandoned
    routeoptionalstringValues:premiumotpla_dedicada
    torequiredstring
    providerrequiredstringValues:aws-snsaws-eumpontaltechccx-sandbox
    encodingoptionalstringValues:GSM-7UCS-2
    lengthoptionalinteger
    segmentsoptionalinteger
    createdAtrequiredstring · date-time
    sentAtoptionalstring · date-time
    deliveredAtoptionalstring · date-time
    failedAtoptionalstring · date-time
    providerReceiptoptionalobject
    providerReceipt.idrequiredstring
    providerReceipt.typerequiredstringValues:api_messageapi_fastapi_reply
    providerReceipt.torequiredstring
    providerReceipt.messageoptionalstring
    providerReceipt.referenceoptionalstring
    providerReceipt.statusrequiredstring
    providerReceipt.statusDescriptionrequiredstring
    providerReceipt.receivedoptionalstring
    providerReceipt.bill_factoroptionalnumber
    providerReceipt.account_idoptionalnumber
    providerReceipt.account_referenceoptionalstring
    providerReceipt.channeloptionalstring | nullValues:SMSRCSWHATSAPP
    contactIdoptionalstring
    campaignIdoptionalstring
    metadataoptionalobjectMetadados de correlação do seu sistema (ex.: customerId, journeyId), devolvidos intactos em todo webhook desta mensagem. Até 20 chaves; chave começa por letra e usa [A-Za-z0-9_.-] (até 64); valor é texto (até 256), número ou booleano. Não envie dado pessoal aqui.
    JSON
    {  "id": "string",  "status": "queued",  "env": "live",  "reason": "invalid_number",  "route": "premium",  "to": "string",  "provider": "aws-sns",  "encoding": "GSM-7",  "length": 0,  "segments": 1,  "createdAt": "2026-10-16T12:00:00.000Z",  "sentAt": "2026-10-16T12:00:00.000Z",  "deliveredAt": "2026-10-16T12:00:00.000Z",  "failedAt": "2026-10-16T12:00:00.000Z",  "providerReceipt": {    "id": "string",    "type": "api_message",    "to": "string",    "message": "string",    "reference": "string",    "status": "string",    "statusDescription": "string",    "received": "string",    "bill_factor": 0,    "account_id": 0,    "account_reference": "string",    "channel": "SMS"  },  "contactId": "string",  "campaignId": "string",  "metadata": {}}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl 'https://api.messages.ccxcompany.co/v2/sms/messages/<id>' \  -H "Authorization: Bearer $CCX_API_KEY"
Required fields only. Swap the sample values for your own.

Lista respostas (MO) aos seus SMS

GET/v2/sms/replies

As mensagens que os destinatários mandaram de volta aos SMS enviados por você, da mais recente para a mais antiga. limit default 50, teto 200. Use inReplyTo para as respostas a um SMS.

Cada resposta chega também no webhook como sms.received, e no bind SMPP (receiver/transceiver) que enviou o SMS original, como deliver_sm.

Short code compartilhado. As rotas premium e otp saem por short code compartilhado entre vários remetentes. Nele, quem associa a resposta ao SMS original é o provedor de envio, e a CCX não tem como conferir essa associação.

Preço: R$ 0,02 por resposta recebida, cobrado uma vez por resposta.

A lista é do ambiente da credencial que lê.

Permissão: sms:read.

Parameters

FieldInTypeDescription
inReplyTooptionalquerystring
fromoptionalquerystring · date-time
tooptionalquerystring · date-time
limitoptionalqueryinteger
skipoptionalqueryinteger

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    itemsrequiredobject[]
    items[].idrequiredstring
    items[].envrequiredstringValues:livetest
    items[].inReplyTorequiredstring
    items[].routeoptionalstringValues:premiumotpla_dedicada
    items[].fromrequiredstring
    items[].bodyrequiredstring
    items[].receivedAtrequiredstring · date-time
    items[].createdAtrequiredstring · date-time
    totalrequiredinteger
    JSON
    {  "items": [    {      "id": "string",      "env": "live",      "inReplyTo": "string",      "route": "premium",      "from": "string",      "body": "string",      "receivedAt": "2026-10-16T12:00:00.000Z",      "createdAt": "2026-10-16T12:00:00.000Z"    }  ],  "total": 0}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 422RFC 7807 problem details for VALIDATION_ERROR (422).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl 'https://api.messages.ccxcompany.co/v2/sms/replies' \  -H "Authorization: Bearer $CCX_API_KEY"
Required fields only. Swap the sample values for your own.

Lê uma resposta (MO) pelo id

GET/v2/sms/replies/{id}

Uma resposta recebida. inReplyTo é o id do SMS ao qual ela responde.

Short code compartilhado. As rotas premium e otp saem por short code compartilhado entre vários remetentes. Nele, quem associa a resposta ao SMS original é o provedor de envio, e a CCX não tem como conferir essa associação.

Preço: R$ 0,02 por resposta recebida, cobrado uma vez por resposta.

Permissão: sms:read.

Parameters

FieldInTypeDescription
idrequiredpathstring

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    idrequiredstring
    envrequiredstringValues:livetest
    inReplyTorequiredstring
    routeoptionalstringValues:premiumotpla_dedicada
    fromrequiredstring
    bodyrequiredstring
    receivedAtrequiredstring · date-time
    createdAtrequiredstring · date-time
    JSON
    {  "id": "string",  "env": "live",  "inReplyTo": "string",  "route": "premium",  "from": "string",  "body": "string",  "receivedAt": "2026-10-16T12:00:00.000Z",  "createdAt": "2026-10-16T12:00:00.000Z"}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

  • 403RFC 7807 problem details for FORBIDDEN (403).

  • 404RFC 7807 problem details for NOT_FOUND (404).

Error responses follow RFC 7807 (application/problem+json), with a stable code in the code field. See the error codes

curl example

cURL
curl 'https://api.messages.ccxcompany.co/v2/sms/replies/<id>' \  -H "Authorization: Bearer $CCX_API_KEY"
Required fields only. Swap the sample values for your own.

Stuck on a route? Talk to the people who run the API.

Sign up through the site and get a US$5 test credit.