One API

One API

One endpoint and one API key for every messaging channel, with declarative fallback routing when a channel fails to deliver.

EndpointPOST /messages/send
Versionv1

Overview

One API is a single endpoint that sends a message over whichever channel you name, and automatically retries the next channel in a chain you define when the first one fails. It replaces five request shapes, five error conventions and five sets of retry logic with one contract.

It is additive. Every dedicated endpoint under /v1/whatsapp, /v1/sms, /v1/rcs, /v1/email and /v1/instagram keeps working exactly as before, including campaigns, templates and per-channel analytics that only exist there.

NoteLooking for the business case rather than the contract? The One API overview covers what it replaces and why. This page is the technical reference.

Supported channels

Five channels are reachable through the unified endpoint. Voice uses its own endpoint because a call is not a message, but it authenticates with the same key.

ChannelWhat it sendsAvailability
WhatsApp Business messagingTemplate and session messages delivered over WhatsApp Business.Unified endpoint
SMSTransactional and promotional SMS with sender ID and route control.Unified endpoint
RCSRich, branded messaging for RCS-capable Android devices.Unified endpoint
EmailTemplated transactional email with full merge-variable support.Unified endpoint
Instagram messagingDirect messages to customers who first reached out on Instagram.Unified endpoint
VoiceOutbound and inbound calling, transcription, and recording.Dedicated endpoint ยท same key
WarningOnly phone-based channels can fall back to one another. WhatsApp, SMS and RCS share a recipient field, so they chain. Email and Instagram address a different identifier and are always sent as the only channel in the request.

Sending a message

POST /messages/send

Send a message over a single channel. The example below delivers a WhatsApp template with two positional variables.

terminal
curl -X POST https://slide.synquic.com/api/v1/messages/send \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "channel": "whatsapp",
    "template": {
      "name": "order_confirmation",
      "languageCode": "en",
      "variables": { "1": "John", "2": "ORD-12345" }
    }
  }'

Request body

FieldTypeRequiredDescription
tostringYesRecipient. A phone number in E.164 for WhatsApp, SMS and RCS. An email address for email. An Instagram-scoped user id for Instagram.
channelstringYesPrimary channel to attempt first: whatsapp, sms, rcs, email or instagram.
fallbackChannelsstring[]NoOrdered channels to try if the primary fails. Phone-based channels only, and every channel named here needs its own send scope on the key.
messagestringConditionalPlain text body. Required for any channel that is not sending a template.
templateobjectConditionalTemplate name, languageCode and positional variables. Required for a WhatsApp template send.
smsobjectNoPer-channel overrides applied only when the SMS channel is used, such as senderId.

Response

Every response carries the channel that actually delivered the message and the full ordered list of attempts, whether or not a fallback was needed.

FieldTypeDescription
statusstringsent when a channel delivered, failed when every channel in the chain failed.
channelUsedstringThe channel that actually delivered the message. Not necessarily the one requested.
messageIdstringProvider message id for the delivering channel, for reconciling against logs and webhooks.
attemptsobject[]Every attempt in order, each with its channel, status and an error string when it failed. Present even on a first-try success.

Fallback routing

How the chain resolves

Set fallbackChannels and One API walks the chain in order: it attempts the primary channel, and on failure moves to the next entry until one delivers or the list is exhausted. There is no orchestration code on your side and no polling. If every channel fails you get a single 502 carrying the complete attempt log.

NoteScopes are checked for every channel named in the request, not just the primary one. A request with channel: "whatsapp" and fallbackChannels: ["sms"] needs both whatsapp:send and sms:send on the key, or it returns 403 naming the missing scope.

Worked example

WhatsApp first, SMS if it does not land. The sms object holds overrides that apply only if the SMS leg is actually used.

terminal
curl -X POST https://slide.synquic.com/api/v1/messages/send \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "channel": "whatsapp",
    "fallbackChannels": ["sms"],
    "message": "Your order ORD-12345 has shipped!",
    "template": { "name": "order_shipped", "languageCode": "en" },
    "sms": { "senderId": "ACMEIN" }
  }'

Reading the attempts array

Here WhatsApp failed and SMS delivered. channelUsed is the one that worked, and every attempt is listed in the order it was made, so you can log exactly what happened without a second API call.

response.json
{
  "status": "sent",
  "channelUsed": "sms",
  "messageId": "sms_9f2a1c8e7b3d",
  "attempts": [
    {
      "channel": "whatsapp",
      "status": "failed",
      "error": "Template not delivered to this recipient"
    },
    {
      "channel": "sms",
      "status": "sent",
      "messageId": "sms_9f2a1c8e7b3d"
    }
  ]
}

Authentication and scopes

One API uses the same bearer token as every other endpoint. There is nothing new to provision: a key that already carries the per-channel send scopes works immediately.

terminal
curl -X POST https://slide.synquic.com/api/v1/messages/send \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "+919876543210", "channel": "sms", "message": "Hello" }'
Channel in the requestScope the key must carry
whatsappwhatsapp:send
smssms:send
rcsrcs:send
emailemail:send
instagraminstagram:send

Create and scope keys from API keys in the dashboard. Rate limits are shared with the dedicated endpoints rather than additional to them, see rate limits.

Errors

Standard HTTP semantics, plus one outcome specific to this endpoint: a 502 means the chain was walked in full and nothing delivered.

StatusMeaningWhen it happens
400Bad requestA required field is missing, or a fallback chain mixes phone-based channels with email or Instagram.
403Missing scopeThe key lacks a send scope for a channel named in the request. The body names the exact scope. Every channel in the chain is checked, not just the primary.
429Rate limitedThe per-key limit was exceeded. Shared with the dedicated endpoints, not additional to them.
502All channels failedEvery channel in the chain was attempted and none delivered. The full attempts array comes back so you know what to retry.

FAQ

QuestionAnswer
Do I need a new API key?No. The same key and the same channel scopes you already have work with One API today.
Can I still use the per-channel APIs?Yes. One API is additive. Campaigns, templates and per-channel analytics continue to live in the dedicated endpoints.
Does a fallback cost more?You are billed per delivered message at the normal rate for whichever channel delivered it. A failed attempt is not billed.
Can email and Instagram be in a chain?No. They address a different recipient identifier from the phone-based channels and are always sent alone.

Ready to send?

Create a key, then send your first unified message in a single request.