REST API reference for Relay Solution: send SMS and WhatsApp messages, manage contacts, segments and campaigns, and read delivery logs. 47 endpoints, authenticated with a single API key. This page is public — no account needed to read it.
Two hosts, one API key
Generate a REST API key in the portal, then send it as
Authorization: Bearer <key> or X-API-Key. One key works
for both hosts. Which host serves a request is decided entirely by its path:
GW
Messaging — send SMS and WhatsApp, read and write contact tags and
CDP attributes. Every path under /api/v1/. https://ops.relay.cequens.com
CP
Management API — contacts, segments, campaigns, message logs, apps
and billing reads. Every path under /api/mgmt/v1/. A key must have
Management API access enabled, which is a per-key setting in the portal. https://portal.relay.cequens.com
The messaging host sends no CORS headers, so those endpoints are server-to-server
only — they cannot be called from a browser.
Platform
Platform connectivity check — no authentication required, useful for uptime monitoring. Every other endpoint uses API key auth (Authorization: Bearer <key> or X-API-Key: <key>).
GET/api/healthMessaging host
Platform health check
Returns the connectivity status of MongoDB and NATS. No authentication required — useful for uptime monitoring.
cURL
curl -X GET "https://ops.relay.cequens.com/api/health" \
-H "Content-Type: application/json"
JavaScript
const res = await fetch("https://ops.relay.cequens.com/api/health", {
method: "GET",
headers: {
"Content-Type": "application/json"
},
});
const data = await res.json();
console.log(data);
CRM for managing subscribers — create, query, import and delete contacts. Also includes the gateway API Key endpoints for reading and updating contacts and CDP attributes programmatically; those run on the messaging host, the rest on the management host. Each endpoint below names the host that serves it.
GET/api/mgmt/v1/contactsManagement hostAPI key
List contacts
Paginated contact list. Supports filtering by status, segment, tag, and full-text search.
Returns tags and CDP attributes for a phone number via API key. Returns 404 if the contact has never been seen by your account. **Served by the SMS gateway host, not the portal host** (see the base URL in the examples below).
Sets or updates CDP attributes. Existing keys not in the payload are preserved. Max 50 key-value pairs per request. Values are stored as strings. **Served by the SMS gateway host, not the portal host.**
Send SMS via the gateway API key, and query, filter, or export the delivery log from the portal. The two sit on different hosts — check the base URL on each endpoint.
GET/api/mgmt/v1/sendersManagement hostAPI key
Get available sender IDs
Returns all approved sender IDs for the organisation.
Submits an outbound SMS through the gateway routing pipeline. Returns 202 Accepted when queued. Pass the API key as Authorization: Bearer <key> or X-API-Key: <key>. **Served by the SMS gateway host, not the portal host** (see the base URL in the examples below).
Request body
from — registered Sender ID. to — E.164 destination. campaignId — optional, links the log to a campaign.
Send to up to 1,000 recipients in one call. Use {variable} placeholders in text for per-recipient personalization. The entire request counts as 1 TPS unit. App limits are enforced automatically from the API key — no appId needed in the body. If quota covers only part of the batch, the first N are queued and the rest returned as quota_exhausted rejections. DND and content-filter checks happen downstream at dispatch time. **Served by the SMS gateway host, not the portal host** (see the base URL in the examples below).
Request body
text supports {variable} placeholders (case-insensitive replacement). Recipients without variables receive the raw template (broadcast mode). App quota is resolved from the API key automatically. Max 1,000 recipients per call.
curl -X POST "https://ops.relay.cequens.com/api/v1/sms/messages/bulk" \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"from":"BRAND","text":"Hi {name}, your order {orderId} is ready for pickup!","recipients":[{"to":"+12025551001","variables":{"name":"Alice","orderId":"A-123"}},{"to":"+12025551002","variables":{"name":"Bob","orderId":"B-456"}},{"to":"+12025551003"}],"campaignId":"64f1..."}'
{
"note": "Returns text/csv — use in a download link or curl -o export.csv"
}
WhatsApp
Send WhatsApp messages via your registered numbers. Supports template, text, and media (image / document / audio / video / sticker). Same API-key auth as SMS, and like SMS these routes run on the SMS gateway host, not the portal host.
Submits an outbound template message through Meta Cloud API. The only message type allowed when the contact has no open 24h service window. **Served by the SMS gateway host, not the portal host** (see the base URL in the examples below). Pass API key as Authorization: Bearer <key> or X-API-Key: <key>. Idempotency-Key header (optional): identical key from the same account returns the previously-queued messageId without re-sending.
Request body
from — your registered WhatsApp number (E.164 or phoneNumberId). to — E.164 destination. template.name — Meta-approved template name. template.language — locale code (must be APPROVED for that template). template.variables — positional map matching {{1}}, {{2}}, … placeholders in the template body. For advanced cases pass template.components (Meta-shape) directly instead of variables.
Free-form text. Only allowed when the recipient has messaged you within the last 24 hours (open service window). Outside the window, use a template send.
Request body
text.body — message text (max 4096 chars). text.preview_url — set true to render link previews. replyToWamid — optional: thread this message as a reply to a previous inbound.
{
"from": "+31644102243",
"to": "+12025551234",
"type": "text",
"text": {
"body": "Thanks for reaching out — your order will ship today.",
"preview_url": false
},
"replyToWamid": "wamid.HBgL…"
}
cURL
curl -X POST "https://ops.relay.cequens.com/api/v1/whatsapp/messages" \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"from":"+31644102243","to":"+12025551234","type":"text","text":{"body":"Thanks for reaching out — your order will ship today.","preview_url":false},"replyToWamid":"wamid.HBgL…"}'
JavaScript
const res = await fetch("https://ops.relay.cequens.com/api/v1/whatsapp/messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer <api_key>"
},
body: JSON.stringify({
"from": "+31644102243",
"to": "+12025551234",
"type": "text",
"text": {
"body": "Thanks for reaching out — your order will ship today.",
"preview_url": false
},
"replyToWamid": "wamid.HBgL…"
}),
});
const data = await res.json();
console.log(data);
Responses
202
Queued
{
"messageId": "wa_…",
"status": "queued"
}
409
Service window closed
{
"error": "No open 24h service window for this contact — use a template send instead",
"code": "service_window_closed"
}
Send image, document, audio, video, or sticker. Same service-window rules as text. Provide either link (public HTTPS URL Meta fetches) or id (a Meta media id from a prior upload).
Request body
For document add filename. For audio and sticker, captions are not supported. Replace the image key with document / audio / video / sticker to match the chosen type.
{
"from": "+31644102243",
"to": "+12025551234",
"type": "image",
"image": {
"link": "https://cdn.example.com/orders/abc.jpg",
"caption": "Your order is on its way!"
}
}
cURL
curl -X POST "https://ops.relay.cequens.com/api/v1/whatsapp/messages" \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"from":"+31644102243","to":"+12025551234","type":"image","image":{"link":"https://cdn.example.com/orders/abc.jpg","caption":"Your order is on its way!"}}'
JavaScript
const res = await fetch("https://ops.relay.cequens.com/api/v1/whatsapp/messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer <api_key>"
},
body: JSON.stringify({
"from": "+31644102243",
"to": "+12025551234",
"type": "image",
"image": {
"link": "https://cdn.example.com/orders/abc.jpg",
"caption": "Your order is on its way!"
}
}),
});
const data = await res.json();
console.log(data);
Responses
202
Queued
{
"messageId": "wa_…",
"status": "queued"
}
400
Media reference missing
{
"error": "image requires either `image.link` (public HTTPS URL) or `image.id` (Meta media id)"
}
Returns the current status and Meta wamid for a previously-submitted message. **Served by the SMS gateway host, not the portal host** (see the base URL in the examples below).
Parameters
Name
In
Type
Description
messageId *
path
string
The messageId returned by POST /api/v1/whatsapp/messages wa_lxky9z_a1b2c3d4