Send a message to a contact

send a caller-supplied message to a contact on a channel. Channels: email, sms, whatsapp, facebook, instagram.

POST https://api.centerfy.ai/webhooks/inbound/messages

Headers

HeaderRequiredValueDescription
x-api-keyYesyour sub-account API key (cfy_…)Authenticates the request; or Authorization: Bearer <key>.
Content-TypeYesapplication/jsonRequest body is JSON.

Body parameters

NameTypeRequiredDefaultDescription
channelstringYes—The delivery channel. One of: email, sms, whatsapp, facebook, instagram (case-insensitive). 400 otherwise.
contact_idstringYes—UUID of the contact to message. Must be a valid UUID (400) and exist (404). The recipient address/number is always derived from this contact — you cannot pass a raw address.
messagestringNo—The message body text. Required for sms, whatsapp, facebook, instagram. For email it is optional, but either message or html must be provided (sent as the email’s text part when html is absent).
subjectstringNo—Email only. Required when channel=‘email’ (400 ‘subject is required for email’ otherwise). Ignored on other channels.
htmlstringNo—Email only. HTML body; takes precedence over message. For email, message or html is required.
reply_tostringNo—Email only. Optional Reply-To address.
from_namestringNo—Email only. Optional sender display name.
from_numberstringNo—SMS only. Optional E.164 from-number override (e.g. +14155550123). 400 if provided but not valid E.164.
attachment_urlsarrayNo—Optional array of attachment URLs. Used by sms (MMS), whatsapp (sent as media), and facebook/instagram. Ignored where not applicable.

Request body

{
  "channel": "sms",
  "contact_id": "<contact_id>",
  "message": "Hi! Your appointment is confirmed for tomorrow at 10am.",
  "from_number": "+14155550123",
  "attachment_urls": [
    "https://cdn.example.com/files/flyer.pdf"
  ]
}

Example

curl -X POST "https://api.centerfy.ai/webhooks/inbound/messages" \
  -H "x-api-key: $CENTERFY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "channel": "sms",
  "contact_id": "<contact_id>",
  "message": "Hi! Your appointment is confirmed for tomorrow at 10am.",
  "from_number": "+14155550123",
  "attachment_urls": [
    "https://cdn.example.com/files/flyer.pdf"
  ]
}'
import { CenterfyClient } from "@centerfy/sdk";

const centerfy = new CenterfyClient({ apiKey: process.env.CENTERFY_API_KEY! });

const result = await centerfy.messages.send({
  "channel": "sms",
  "contact_id": "<contact_id>",
  "message": "Hi! Your appointment is confirmed for tomorrow at 10am.",
  "from_number": "+14155550123",
  "attachment_urls": [
    "https://cdn.example.com/files/flyer.pdf"
  ]
});
console.log(result);
centerfy messages send '{"channel":"sms","contact_id":"<contact_id>","message":"Hi! Your appointment is confirmed for tomorrow at 10am.","from_number":"+14155550123","attachment_urls":["https://cdn.example.com/files/flyer.pdf"]}'

MCP tool: centerfy_messages_send (see MCP server)

Response

{
  "status": "success",
  "channel": "sms",
  "contact_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "message_id": "SM0f3a2b1c9d8e7f6a5b4c3d2e1f0a9b8c"
}

Errors

  • 400 — bad channel, invalid contact_id, missing subject for email, missing message/html for email, missing message on other channels, contact missing the needed email/phone/WhatsApp address, invalid from_number, or fb/ig cold-send.
  • 401 — missing or invalid key.
  • 402 — insufficient wallet balance.
  • 404 — contact not found.
  • 502 — send failed.

Notes

The recipient is always derived from the contact — no raw address can be passed. The message is attributed as a human-sent message. facebook/instagram require an existing conversation (no cold outbound) — 400 otherwise.

© 2026 Centerfy AI. All rights reserved.