Start free

API reference

WhatsApp messages

Send WhatsApp messages (text, template, media or flow) from one of your numbers, list the history with filters and check the status of each send.

  • 3 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.

List messages

GET/messages

Paginated list. Filters: status, numberId, contactId, campaignId, batchId, sentByAccountId, from, to, limit, skip. Default order is createdAt desc.

PII fields (recipient to) are masked unless the caller has pii:full.

Parameters

FieldInTypeDescription
statusoptionalquerystringValues:queuedsendingsentdeliveredreadfailedarchived
numberIdoptionalquerystringBranded Number id (num_ prefix + 21 nano-id chars).
contactIdoptionalquerystringBranded Contact id (cnt_ prefix + 21 nano-id chars).
campaignIdoptionalquerystringFilter by external campaign tag. Used by the dashboard to scope a 'reprocess all failures of this campaign' action.
batchIdoptionalquerystringBranded batch id (btc_ prefix + 21 nano-id chars).
sentByAccountIdoptionalquerystringFilter by the operator who sent the message. Powers the dashboard's per-agent view, where every counter has to follow the selected attendant.
fromoptionalquerystring · date-timeISO-8601 timestamp in UTC.
tooptionalquerystring · date-timeISO-8601 timestamp in UTC.
limitoptionalqueryinteger
skipoptionalqueryinteger

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    itemsrequiredobject[]
    items[].idrequiredstringBranded Message id (msg_ prefix + 21 nano-id chars).
    items[].organizationIdrequiredstringBranded Organization id (org_ prefix + 21 nano-id chars).
    items[].channeloptionalstringCanal da mensagem. Ausente em linhas antigas, anteriores ao campo — leia como whatsapp.Values:whatsappemailsmsinstagram
    items[].numberIdoptionalstringBranded Number id (num_ prefix + 21 nano-id chars).
    items[].instagramAccountIdoptionalstringBranded Instagram account id (iga_ prefix + 21 nano-id chars).
    items[].mediaStorageoptionalobject
    items[].mediaStorage.mimeTypeoptionalstringMime REAL do binário, lido do Content-Type.
    items[].mediaStorage.sizeoptionalinteger
    items[].mediaStorage.storedAtoptionalstring · date-time
    items[].contactIdoptionalstringBranded Contact id (cnt_ prefix + 21 nano-id chars).
    items[].campaignIdoptionalstringOptional external campaign tag carried through from the create call. Surfaced as a filter on GET /messages and as a selector on POST /messages/bulk-resend.
    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.
    items[].templateIdoptionalstringBranded Template id (tpl_ prefix + 21 nano-id chars).
    items[].batchIdoptionalstringBranded batch id (btc_ prefix + 21 nano-id chars).
    items[].torequiredstringDestino, no formato do canal: telefone E.164 (whatsapp/sms), endereço de e-mail (email) ou IGSID (instagram). PII_SENSITIVE — mascarado a menos que o chamador tenha pii:full.
    items[].typerequiredstringValues:texttemplatemediainteractive
    items[].directionrequiredstringValues:outboundinbound
    items[].priorityrequiredstringValues:normalbulkcritical
    items[].statusrequiredstringValues:queuedsendingsentdeliveredreadfailedarchived
    items[].forcerequiredbooleanWhen true the worker bypasses token bucket + quiet hours. Persisted for audit; only the force route sets it.
    items[].reprocessedoptionalbooleanTrue when a dashboard operator manually reprocessed this message. replacedBy points to the new message.
    items[].replacedByoptionalstringBranded Message id (msg_ prefix + 21 nano-id chars).
    items[].payloadrequiredanyOpaque per-type payload (text body, template ref, etc).
    items[].templateVarsoptionalstring[]
    items[].attemptsrequiredinteger
    items[].lastErroroptionalstringMost recent failure reason. After cancelAsReprocessed (or bulk-resend) this is overwritten with a 'substituted by ...' pointer string — see originalError for the underlying cause.
    items[].originalErroroptionalstringSnapshot of lastError taken the first time the message is reprocessed. Audit-trail field — never overwritten on subsequent transitions.
    items[].metaMessageIdoptionalstring
    items[].origemDoLinkoptionalobjectDe onde veio a mensagem que trouxe o código do link de WhatsApp (fonte, campanha, grupo, anúncio e palavra-chave do link) e o código que estava no texto. Só em mensagem recebida.
    items[].origemDoLink.fonteoptionalstringValues:googlemetatiktokoutra
    items[].origemDoLink.fonteRotulooptionalstringO nome livre da fonte (src= do link) quando fonte é outra.
    items[].origemDoLink.campanhaoptionalstring
    items[].origemDoLink.grupooptionalstring
    items[].origemDoLink.anunciooptionalstring
    items[].origemDoLink.palavraChaveoptionalstring
    items[].origemDoLink.codigooptionalstringO código que estava no texto, entre parênteses. O texto da mensagem não é alterado.
    items[].sentByAccountIdoptionalstring
    items[].sentByNameoptionalstringOperator display name (when sent from the dashboard).
    items[].scheduledAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    items[].sentAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    items[].deliveredAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    items[].readAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    items[].failedAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    items[].createdAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    items[].updatedAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    totalrequiredinteger
    JSON
    {  "items": [    {      "id": "msg_aB3xY9zQ1pTkLmNoPqRsT",      "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",      "channel": "whatsapp",      "numberId": "num_aB3xY9zQ1pTkLmNoPqRsT",      "instagramAccountId": "iga_aB3xY9zQ1pTkLmNoPqRsT",      "mediaStorage": {        "mimeType": "string",        "size": 0,        "storedAt": "2026-10-16T12:00:00.000Z"      },      "contactId": "cnt_aB3xY9zQ1pTkLmNoPqRsT",      "campaignId": "string",      "metadata": {        "customerId": "123",        "journeyId": "reativacao-q4"      },      "templateId": "tpl_uV2aLwzXMqNmKjHbPiRoT",      "batchId": "btc_aB3xY9zQ1pTkLmNoPqRsT",      "to": "+5511999998888",      "type": "text",      "direction": "outbound",      "priority": "normal",      "status": "queued",      "force": true,      "reprocessed": true,      "replacedBy": "msg_aB3xY9zQ1pTkLmNoPqRsT",      "payload": null,      "templateVars": [        "string"      ],      "attempts": 0,      "lastError": "string",      "originalError": "string",      "metaMessageId": "wamid.HBgN...",      "origemDoLink": {        "fonte": "tiktok",        "fonteRotulo": "bio",        "campanha": "Verão",        "grupo": "Corredores SP",        "anuncio": "Corrida no parque",        "palavraChave": "tênis de corrida",        "codigo": "K7Q2X"      },      "sentByAccountId": "string",      "sentByName": "string",      "scheduledAt": "2026-04-07T17:30:00.000Z",      "sentAt": "2026-04-07T17:30:00.000Z",      "deliveredAt": "2026-04-07T17:30:00.000Z",      "readAt": "2026-04-07T17:30:00.000Z",      "failedAt": "2026-04-07T17:30:00.000Z",      "createdAt": "2026-04-07T17:30:00.000Z",      "updatedAt": "2026-04-07T17:30:00.000Z"    }  ],  "total": 42}
  • 401RFC 7807 problem details for UNAUTHORIZED (401).

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

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/messages' \  -H "Authorization: Bearer $CCX_API_KEY"
Required fields only. Swap the sample values for your own.

Send a single outbound message

POST/messages

Persists the message + an outbox row in a single Mongo transaction, then attempts an inline Rabbit publish to messages.outbound with routing key matching the priority. Inline publish failures leave the outbox row pending — the worker poller (Step 19) drains stragglers.

Idempotency: optional. Send Idempotency-Key header (or idempotencyKey in the body — when both are present they MUST match) to make the call replayable for 24h. Same key + same fingerprint → original response is returned. Same key + different body → 409 IDEMPOTENCY_CONFLICT.

Priority routing:

  • critical → out.priority queue
  • normal → out.normal queue (default)
  • bulk → out.bulk queue

Corpo por `type` (o `payload` muda conforme o tipo):

  • text → { "type": "text", "payload": { "text": { "body": "Olá!" } } }
  • template → { "type": "template", "payload": { "template": { "name": "boas_vindas", "languageCode": "pt_BR", "components": [] } } } (ou envie templateId + templateVars e a plataforma materializa o template)
  • media (imagem) → { "type": "media", "payload": { "kind": "image", "media": { "link": "https://…/foto.jpg", "caption": "…" } } }
  • media (áudio) → { "type": "media", "payload": { "kind": "audio", "media": { "link": "https://…/audio.ogg" } } }
  • media (vídeo) → { "type": "media", "payload": { "kind": "video", "media": { "link": "https://…/video.mp4", "caption": "…" } } }
  • media (documento) → { "type": "media", "payload": { "kind": "document", "media": { "link": "https://…/fatura.pdf", "filename": "fatura.pdf" } } }
  • media (sticker) → { "type": "media", "payload": { "kind": "sticker", "media": { "link": "https://…/sticker.webp" } } }
  • interactive (flow) → { "type": "interactive", "payload": { "flow": { "metaFlowId": "123…", "flowCta": "Começar", "flowAction": "navigate", "headerText": "…", "bodyText": "…", "mode": "published" } } }

Em media, use media.link (URL pública) OU media.id (mídia já enviada à Meta). caption/filename são opcionais. replyTo (id de mensagem) é aceito em qualquer tipo.

Opt-out: template de MARKETING (templateId com categoria marketing) para contato que pediu para não receber comunicação é recusado com 422 e meta.motivo: "opt_out". Utilidade, autenticação e texto livre na janela de atendimento seguem saindo.

Always returns 201 once the transaction commits — the message IS in the system regardless of the inline publish outcome.

Request bodyapplication/json

FieldTypeDescription
numberIdrequiredstringBranded Number id (num_ prefix + 21 nano-id chars).
torequiredstringE.164 phone (recipient).
typerequiredstringValues:texttemplatemediainteractive
priorityoptionalstringRouting priority. Maps to out.{critical|normal|bulk} queues.Values:normalbulkcriticalDefault:normal
payloadrequiredobjectCorpo por tipo (validado ponta-a-ponta pelo worker contra @ccx/meta): text → { text: { body } }; template → informe templateId (+ templateVars) OU { template: { name, languageCode } }; media → { kind: image|audio|video|document|sticker, media: { link } }; interactive → { flow: { metaFlowId, flowCta } }.
templateIdoptionalstringBranded Template id (tpl_ prefix + 21 nano-id chars).
templateVarsoptionalstring[]
contactIdoptionalstringBranded Contact id (cnt_ prefix + 21 nano-id chars).
campaignIdoptionalstringOptional campaign tag carried through to the persisted message. Used by GET /messages?campaignId=... and POST /messages/bulk-resend filters to scope retries to a single campaign.
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.
scheduledAtoptionalstring · date-timeISO-8601 timestamp in UTC.
idempotencyKeyoptionalstringOptional Stripe-style idempotency key. Also accepted via Idempotency-Key header — when both are present they MUST match (400 otherwise).
Full body example
JSON
{  "numberId": "num_aB3xY9zQ1pTkLmNoPqRsT",  "to": "+5511999998888",  "type": "text",  "priority": "normal",  "payload": {    "text": {      "body": "Olá! Mensagem de teste do CCX."    }  },  "templateId": "tpl_uV2aLwzXMqNmKjHbPiRoT",  "templateVars": [    "Alice",    "ORDER123"  ],  "contactId": "cnt_aB3xY9zQ1pTkLmNoPqRsT",  "campaignId": "string",  "metadata": {    "customerId": "123",    "journeyId": "reativacao-q4"  },  "scheduledAt": "2026-04-07T17:30:00.000Z",  "idempotencyKey": "checkout-12345"}

Responses

  • 201Default Response

    Response fields and example
    FieldTypeDescription
    idrequiredstringBranded Message id (msg_ prefix + 21 nano-id chars).
    organizationIdrequiredstringBranded Organization id (org_ prefix + 21 nano-id chars).
    channeloptionalstringCanal da mensagem. Ausente em linhas antigas, anteriores ao campo — leia como whatsapp.Values:whatsappemailsmsinstagram
    numberIdoptionalstringBranded Number id (num_ prefix + 21 nano-id chars).
    instagramAccountIdoptionalstringBranded Instagram account id (iga_ prefix + 21 nano-id chars).
    mediaStorageoptionalobject
    mediaStorage.mimeTypeoptionalstringMime REAL do binário, lido do Content-Type.
    mediaStorage.sizeoptionalinteger
    mediaStorage.storedAtoptionalstring · date-time
    contactIdoptionalstringBranded Contact id (cnt_ prefix + 21 nano-id chars).
    campaignIdoptionalstringOptional external campaign tag carried through from the create call. Surfaced as a filter on GET /messages and as a selector on POST /messages/bulk-resend.
    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.
    templateIdoptionalstringBranded Template id (tpl_ prefix + 21 nano-id chars).
    batchIdoptionalstringBranded batch id (btc_ prefix + 21 nano-id chars).
    torequiredstringDestino, no formato do canal: telefone E.164 (whatsapp/sms), endereço de e-mail (email) ou IGSID (instagram). PII_SENSITIVE — mascarado a menos que o chamador tenha pii:full.
    typerequiredstringValues:texttemplatemediainteractive
    directionrequiredstringValues:outboundinbound
    priorityrequiredstringValues:normalbulkcritical
    statusrequiredstringValues:queuedsendingsentdeliveredreadfailedarchived
    forcerequiredbooleanWhen true the worker bypasses token bucket + quiet hours. Persisted for audit; only the force route sets it.
    reprocessedoptionalbooleanTrue when a dashboard operator manually reprocessed this message. replacedBy points to the new message.
    replacedByoptionalstringBranded Message id (msg_ prefix + 21 nano-id chars).
    payloadrequiredanyOpaque per-type payload (text body, template ref, etc).
    templateVarsoptionalstring[]
    attemptsrequiredinteger
    lastErroroptionalstringMost recent failure reason. After cancelAsReprocessed (or bulk-resend) this is overwritten with a 'substituted by ...' pointer string — see originalError for the underlying cause.
    originalErroroptionalstringSnapshot of lastError taken the first time the message is reprocessed. Audit-trail field — never overwritten on subsequent transitions.
    metaMessageIdoptionalstring
    origemDoLinkoptionalobjectDe onde veio a mensagem que trouxe o código do link de WhatsApp (fonte, campanha, grupo, anúncio e palavra-chave do link) e o código que estava no texto. Só em mensagem recebida.
    origemDoLink.fonteoptionalstringValues:googlemetatiktokoutra
    origemDoLink.fonteRotulooptionalstringO nome livre da fonte (src= do link) quando fonte é outra.
    origemDoLink.campanhaoptionalstring
    origemDoLink.grupooptionalstring
    origemDoLink.anunciooptionalstring
    origemDoLink.palavraChaveoptionalstring
    origemDoLink.codigooptionalstringO código que estava no texto, entre parênteses. O texto da mensagem não é alterado.
    sentByAccountIdoptionalstring
    sentByNameoptionalstringOperator display name (when sent from the dashboard).
    scheduledAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    sentAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    deliveredAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    readAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    failedAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    createdAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    updatedAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "id": "msg_aB3xY9zQ1pTkLmNoPqRsT",  "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",  "channel": "whatsapp",  "numberId": "num_aB3xY9zQ1pTkLmNoPqRsT",  "instagramAccountId": "iga_aB3xY9zQ1pTkLmNoPqRsT",  "mediaStorage": {    "mimeType": "string",    "size": 0,    "storedAt": "2026-10-16T12:00:00.000Z"  },  "contactId": "cnt_aB3xY9zQ1pTkLmNoPqRsT",  "campaignId": "string",  "metadata": {    "customerId": "123",    "journeyId": "reativacao-q4"  },  "templateId": "tpl_uV2aLwzXMqNmKjHbPiRoT",  "batchId": "btc_aB3xY9zQ1pTkLmNoPqRsT",  "to": "+5511999998888",  "type": "text",  "direction": "outbound",  "priority": "normal",  "status": "queued",  "force": true,  "reprocessed": true,  "replacedBy": "msg_aB3xY9zQ1pTkLmNoPqRsT",  "payload": null,  "templateVars": [    "string"  ],  "attempts": 0,  "lastError": "string",  "originalError": "string",  "metaMessageId": "wamid.HBgN...",  "origemDoLink": {    "fonte": "tiktok",    "fonteRotulo": "bio",    "campanha": "Verão",    "grupo": "Corredores SP",    "anuncio": "Corrida no parque",    "palavraChave": "tênis de corrida",    "codigo": "K7Q2X"  },  "sentByAccountId": "string",  "sentByName": "string",  "scheduledAt": "2026-04-07T17:30:00.000Z",  "sentAt": "2026-04-07T17:30:00.000Z",  "deliveredAt": "2026-04-07T17:30:00.000Z",  "readAt": "2026-04-07T17:30:00.000Z",  "failedAt": "2026-04-07T17:30:00.000Z",  "createdAt": "2026-04-07T17:30:00.000Z",  "updatedAt": "2026-04-07T17:30:00.000Z"}
  • 400RFC 7807 problem details for BAD_REQUEST (400).

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

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

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

  • 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/messages' \  -H "Authorization: Bearer $CCX_API_KEY" \  -H "Idempotency-Key: order-4821" \  -H "Content-Type: application/json" \  -d '{    "numberId": "num_aB3xY9zQ1pTkLmNoPqRsT",    "to": "+5511999998888",    "type": "text",    "payload": {      "text": {        "body": "Olá! Mensagem de teste do CCX."      }    }  }'
Required fields only. Swap the sample values for your own.

Get a single message

GET/messages/{id}

Returns the persisted Message including current status. Cross-tenant requests get 404 (Mongo Guardian filter masks existence).

Parameters

FieldInTypeDescription
idrequiredpathstringBranded Message id (msg_ prefix + 21 nano-id chars).

Responses

  • 200Default Response

    Response fields and example
    FieldTypeDescription
    idrequiredstringBranded Message id (msg_ prefix + 21 nano-id chars).
    organizationIdrequiredstringBranded Organization id (org_ prefix + 21 nano-id chars).
    channeloptionalstringCanal da mensagem. Ausente em linhas antigas, anteriores ao campo — leia como whatsapp.Values:whatsappemailsmsinstagram
    numberIdoptionalstringBranded Number id (num_ prefix + 21 nano-id chars).
    instagramAccountIdoptionalstringBranded Instagram account id (iga_ prefix + 21 nano-id chars).
    mediaStorageoptionalobject
    mediaStorage.mimeTypeoptionalstringMime REAL do binário, lido do Content-Type.
    mediaStorage.sizeoptionalinteger
    mediaStorage.storedAtoptionalstring · date-time
    contactIdoptionalstringBranded Contact id (cnt_ prefix + 21 nano-id chars).
    campaignIdoptionalstringOptional external campaign tag carried through from the create call. Surfaced as a filter on GET /messages and as a selector on POST /messages/bulk-resend.
    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.
    templateIdoptionalstringBranded Template id (tpl_ prefix + 21 nano-id chars).
    batchIdoptionalstringBranded batch id (btc_ prefix + 21 nano-id chars).
    torequiredstringDestino, no formato do canal: telefone E.164 (whatsapp/sms), endereço de e-mail (email) ou IGSID (instagram). PII_SENSITIVE — mascarado a menos que o chamador tenha pii:full.
    typerequiredstringValues:texttemplatemediainteractive
    directionrequiredstringValues:outboundinbound
    priorityrequiredstringValues:normalbulkcritical
    statusrequiredstringValues:queuedsendingsentdeliveredreadfailedarchived
    forcerequiredbooleanWhen true the worker bypasses token bucket + quiet hours. Persisted for audit; only the force route sets it.
    reprocessedoptionalbooleanTrue when a dashboard operator manually reprocessed this message. replacedBy points to the new message.
    replacedByoptionalstringBranded Message id (msg_ prefix + 21 nano-id chars).
    payloadrequiredanyOpaque per-type payload (text body, template ref, etc).
    templateVarsoptionalstring[]
    attemptsrequiredinteger
    lastErroroptionalstringMost recent failure reason. After cancelAsReprocessed (or bulk-resend) this is overwritten with a 'substituted by ...' pointer string — see originalError for the underlying cause.
    originalErroroptionalstringSnapshot of lastError taken the first time the message is reprocessed. Audit-trail field — never overwritten on subsequent transitions.
    metaMessageIdoptionalstring
    origemDoLinkoptionalobjectDe onde veio a mensagem que trouxe o código do link de WhatsApp (fonte, campanha, grupo, anúncio e palavra-chave do link) e o código que estava no texto. Só em mensagem recebida.
    origemDoLink.fonteoptionalstringValues:googlemetatiktokoutra
    origemDoLink.fonteRotulooptionalstringO nome livre da fonte (src= do link) quando fonte é outra.
    origemDoLink.campanhaoptionalstring
    origemDoLink.grupooptionalstring
    origemDoLink.anunciooptionalstring
    origemDoLink.palavraChaveoptionalstring
    origemDoLink.codigooptionalstringO código que estava no texto, entre parênteses. O texto da mensagem não é alterado.
    sentByAccountIdoptionalstring
    sentByNameoptionalstringOperator display name (when sent from the dashboard).
    scheduledAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    sentAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    deliveredAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    readAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    failedAtoptionalstring · date-timeISO-8601 timestamp in UTC.
    createdAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    updatedAtrequiredstring · date-timeISO-8601 timestamp in UTC.
    JSON
    {  "id": "msg_aB3xY9zQ1pTkLmNoPqRsT",  "organizationId": "org_pGgniw5L7CTDSZDwjDrQ2",  "channel": "whatsapp",  "numberId": "num_aB3xY9zQ1pTkLmNoPqRsT",  "instagramAccountId": "iga_aB3xY9zQ1pTkLmNoPqRsT",  "mediaStorage": {    "mimeType": "string",    "size": 0,    "storedAt": "2026-10-16T12:00:00.000Z"  },  "contactId": "cnt_aB3xY9zQ1pTkLmNoPqRsT",  "campaignId": "string",  "metadata": {    "customerId": "123",    "journeyId": "reativacao-q4"  },  "templateId": "tpl_uV2aLwzXMqNmKjHbPiRoT",  "batchId": "btc_aB3xY9zQ1pTkLmNoPqRsT",  "to": "+5511999998888",  "type": "text",  "direction": "outbound",  "priority": "normal",  "status": "queued",  "force": true,  "reprocessed": true,  "replacedBy": "msg_aB3xY9zQ1pTkLmNoPqRsT",  "payload": null,  "templateVars": [    "string"  ],  "attempts": 0,  "lastError": "string",  "originalError": "string",  "metaMessageId": "wamid.HBgN...",  "origemDoLink": {    "fonte": "tiktok",    "fonteRotulo": "bio",    "campanha": "Verão",    "grupo": "Corredores SP",    "anuncio": "Corrida no parque",    "palavraChave": "tênis de corrida",    "codigo": "K7Q2X"  },  "sentByAccountId": "string",  "sentByName": "string",  "scheduledAt": "2026-04-07T17:30:00.000Z",  "sentAt": "2026-04-07T17:30:00.000Z",  "deliveredAt": "2026-04-07T17:30:00.000Z",  "readAt": "2026-04-07T17:30:00.000Z",  "failedAt": "2026-04-07T17:30:00.000Z",  "createdAt": "2026-04-07T17:30:00.000Z",  "updatedAt": "2026-04-07T17:30: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/messages/msg_aB3xY9zQ1pTkLmNoPqRsT' \  -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.