One key, one webhook and every channel.
WhatsApp, SMS, RCS, email and push through the same REST API: the same authentication, the same error format and the same signed webhooks for statuses and replies. Test with a sandbox key before you send for real.
US$5 test credit when you sign up. Test keys never spend it.
curl -X POST https://api.messages.ccxcompany.co/messages \ -H "Authorization: Bearer $CCX_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-4821" \ -d '{ "numberId": "num_…", "to": "+14155550123", "type": "template", "templateId": "tpl_…", "templateVars": ["Marina", "4821"], "metadata": { "order": "4821" } }'
- message.sentSigned · 200Sent to +1 415 555 0123
- message.deliveredSigned · 200Delivered · metadata.order 4821
- message.readSigned · 200Read by the customer
- message.receivedSigned · 200Customer replied: “Thanks, see you today!”
One send. One response.
The WhatsApp route takes the sending number, the recipient, the type and the content. The message is queued right away, and its status reaches your webhook later. Pick a field to see it in the call.
curl -X POST https://api.messages.ccxcompany.co/messages \ -H "Authorization: Bearer $CCX_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: order-4821" \ -d '{ "numberId": "num_…", "to": "+14155550123", "type": "template", "templateId": "tpl_…", "templateVars": ["Marina", "4821"], "metadata": { "order": "4821" } }'
Outside the 24-hour window, WhatsApp only accepts approved templates. The full message object is in openapi.json.
Each channel has its own route. Everything else is the same.
The body changes by channel. The key, the error format and the webhooks work the same way on all of them.
Statuses and replies reach you, signed.
Subscribe a URL and pick the events. Before it goes live, CCX checks the address and sends a signed ping.
- 5 s
- 30 s
- 2 min
- 10 min
- 1 h
POST https://your-system.com/webhooks/ccxX-CCX-Signature: t=1791300000,v1=5f2c…X-CCX-Event: message.deliveredX-CCX-Delivery-Id: …X-CCX-Idempotency-Key: … { "event": "message.delivered", "messageId": "msg_…", "channel": "whatsapp", "metadata": { "order": "4821" }, "occurredAt": "2026-10-06T14:02:11Z"}
Sample webhook delivery, trimmed.
Test all you want. Send for real when you're ready.
A test key behaves like a production key, but sends go through a simulated transport and draw from a test wallet you top up for free in the dashboard. In the playground, every public route becomes a form you run from the browser.
Contacts, lists, journeys and pipeline, with the same key.
The public contract has 125 operations, all in the OpenAPI document.
Contacts and opt-out
Create, update, bulk import and record who asked not to be contacted.
/contacts/contacts/importLists and segments
Static lists and saved segments, for campaigns and journeys.
/v2/lists/v2/segmentsJourneys and events
Create journeys, add contacts to them and record purchases for attribution.
/v2/journeys/v2/eventsSales pipeline
Pipelines, stages and cards, with fields, activities and files.
/pipelinesTemplates and flows
Create draft templates and read WhatsApp templates and flows.
/v2/templates/v2/flowsExports, balance and numbers
Export each channel's messages by period, and check your balance and each number's health.
/v2/exports/{channel}/walletAPI calls are free. You pay for messages.
Each message goes out at its channel's published price. The monthly plan covers your whole team, with no per-seat fees.
See full pricing| What you use | Price | 1,000 messages |
|---|---|---|
| API callsEvery route, every key | No charge | No charge |
| WhatsApp utilityTo the United States | US$0.0084 | US$8.40 |
| EmailAny destination | US$0.0004 | US$0.40 |
| Push notificationAPNs, FCM or Web Push | US$0.0002 | US$0.20 |
| Monthly planYour whole team, no seat fees | from US$39/mo | Flat, per month |
International price list in US dollars, euros for eurozone destinations. WhatsApp is priced by destination country and message category. SMS is priced for Brazilian numbers; international routes are on request.
Is the API versioned in the path?
There's no single prefix: WhatsApp sending is POST /messages and newer channels live under /v2, like /v2/sms/messages. The public OpenAPI document is the reference for every route.
Do I need the SDK?
No. It's REST with JSON, and the cURL above is enough. The TypeScript SDK generates the Idempotency-Key for you and returns typed errors.
How does idempotency work?
Send the Idempotency-Key header with a value of your own, like the order number. On WhatsApp, the same key within 24 hours returns the original message; the same key with a different body returns 409.
What's the rate limit?
Past the limit, the API answers 429 RATE_LIMITED with a Retry-After header telling you when to try again. If your volume needs more, talk to us.
How do I get delivery status?
Through signed webhooks, with the events you pick. If you'd rather poll, GET /messages/{id} returns the message's status.
Do you support SMPP for SMS?
Yes, over a TLS-encrypted connection, for teams that already have an SMPP client and don't want to rewrite it. CCX's SMS goes to Brazilian numbers.
Where is the full reference?
In the public OpenAPI document at ccxmessages.com/openapi.json. Anything not in it isn't contract and may change.
Your first call starts with a test key.
Sign up through the site and get a US$5 test credit.