Skip to content

Sending messages

One endpoint, all three channels:

Terminal window
curl -X POST https://api.neike.dev/api/outbound/send \
-H "x-neike-api-key: whk_live_…" \
-H "Content-Type: application/json" \
-d '{
"channelId": "nk_dvzobn7m4h4y",
"to": "5491112345678",
"type": "text",
"content": { "text": "Yes, we do." }
}'
{ "ok": true, "jobId": "outbound_nk_dvzobn7m4h4y_1712345678901" }

202 means queued, not delivered. Delivery arrives on your webhook as a status update.

to is the counterpart’s identifier for that platform:

Channelto
WhatsAppPhone number in E.164 without + — 5491112345678
InstagramThe IGSID you received in the inbound message
MessengerThe PSID you received in the inbound message

For Instagram and Messenger you cannot invent a recipient: you can only reply to someone who wrote to you first, using the id from their message.

content changes shape with type:

{ "type": "text", "content": { "text": "Hello" } }
{
"type": "image",
"content": { "image": { "link": "https://…/photo.jpg", "caption": "Optional" } }
}
{
"type": "document",
"content": { "document": { "link": "https://…/invoice.pdf", "filename": "invoice.pdf" } }
}

Media is sent by link: the URL has to be publicly reachable so Meta can fetch it. Size and format limits are Meta’s, and they differ per channel.

POST /api/messages/typing shows “typing” to a contact. It is synchronous: Neike calls Meta during the request and answers 200 with { "ok": true }. It is not queued, it does not draw from your balance and it does not take an Idempotency-Key. It needs the messages:send scope.

{ "channelId": "nk_dvzobn7m4h4y", "to": "1234567890123456", "action": "typing_on" }
  • Instagram and Messenger: to (the IGSID or PSID) is required. action is typing_on (default) or typing_off.
  • WhatsApp: send messageId (the wamid of the inbound message) instead of to. Only typing_on exists: the indicator lasts up to 25 seconds or until you reply, and typing_off returns 400. The indicator also marks that inbound message as read (blue ticks). WhatsApp has no way to show the indicator without marking the message as read.

Errors:

StatusMeaning
400Invalid request (missing channelId, to or messageId, bad action).
404The channel does not exist or is out of scope for your credential.
422Meta rejected the request (invalid contact or message, 24-hour window over).
429Meta rate limit.
502Meta did not answer or failed.

On 422, 429 and 502 the message includes Meta’s own text.

Meta only lets you message freely within 24 hours of the customer’s last message. After that:

  • WhatsApp — you must use an approved template. See Templates.
  • Instagram — you can send outside the window with the human agent tag, by passing "humanAgent": true. Use it only when a person is actually replying; misusing it puts the channel at risk.

Each outbound message draws from your prepaid wallet at Meta’s conversation rate. Without enough balance the call returns 402 and nothing is queued. Inbound messages are never blocked by balance.