Command Palette

Search for a command to run...

IntelliPortalDOCS

Start here

  • Overview
  • Quickstart
  • Test in the sandbox

Build

  • Authentication
  • Clients
  • Hosted onboarding
  • Webhooks

API reference

  • Messages
  • Usage
  • Status & observability

Reliability

  • WhatsApp limits
  • Errors & debugging

Resources

  • Changelog
  • OpenAPI 3.1
  • Postman collection
Developer support
IntelliPortalDOCS
Developer documentation/API v1

© 2026 Intelli Holdings Inc.

PrivacyContact

Need a hand?

Share a request ID when you contact us so we can trace the call quickly.

Open developer support
  1. Docs
  2. Messages

API reference

messages:send

Messages

Send through a connected client using a Meta-compatible payload. IntelliPortal resolves the channel from client_ref and normalizes authentication, errors, request logging, and test mode.

POST/messages/send

Send a free-form message

Send from your backend with a key that has messages:send. The property named by type is forwarded in Meta's shape.

cURL
curl -X POST https://api.intelliconcierge.dev/v1/messages/send \
  -H "Authorization: Bearer $INTELLI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "client_ref": "customer_42",
    "to": "+254700000000",
    "type": "text",
    "text": { "body": "Your order is ready." }
  }'
PropertyTypeDescription
client_refrequiredstringYour stable identifier for the connected client and channel used to send.
torequiredstringWhatsApp recipient phone number or Instagram-scoped user ID from a webhook.
typerequiredenumSelects the matching payload object: text, image, video, audio, document, sticker, location, contacts, interactive, or reaction.
<type>requiredobjectThe payload whose property name matches type. Its shape mirrors Meta's Cloud API.
dry_runbooleanValidate without delivery. Always treated as true for ik_test_ keys.

WhatsApp message types

Media can use a public HTTPS link or an uploaded Meta media id. Free-form sends require an open 24-hour customer-service window.

typePayload essentials
textbody; optional preview_url
imagelink or id; optional caption
videolink or id; optional caption
audiolink or id
documentlink or id; optional caption and filename
stickerlink or id
locationlatitude, longitude; optional name and address
contactsArray of Meta contact objects
interactivebutton, list, cta_url, and other Meta interactive shapes
reactionmessage_id and emoji; an empty emoji removes the reaction
Request body examples
{
  "client_ref": "customer_42",
  "to": "+254700000000",
  "type": "text",
  "text": {
    "body": "Your order is ready.",
    "preview_url": false
  }
}
POST/messages/send-template

Send an approved template

Templates are WhatsApp-only and can open a conversation outside the 24-hour service window. The name, language, and components must match an approved template on the client's WhatsApp Business Account.

JSON
{
  "client_ref": "customer_42",
  "to": "+254700000000",
  "template": {
    "name": "order_ready",
    "language": { "code": "en_US" },
    "components": [
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "1842" }
        ]
      }
    ]
  }
}

Channel routing

Do not send a separate channel parameter. IntelliPortal looks up the client and routes through its connected channel.

Instagram takes text and media

For an Instagram client, set to to the Instagram-scoped sender ID from a webhook. Text is limited to 1,000 characters and must be sent inside Instagram's reply window.

image, video, audio and document are supported and must carry link — Instagram fetches media from a public HTTPS URL and cannot use an uploaded media id, which returns media_link_required. A caption or filename has nowhere to go on an Instagram attachment, so the send succeeds and reports it under warnings; send the caption as its own text message if you need it.

sticker, location, contacts, interactive and reaction have no Instagram equivalent and return channel_type_unsupported.

Response

Store message_id to correlate later delivery status webhooks. Also capture the X-Request-Id response header for operational tracing.

JSON · live
{
  "success": true,
  "message_id": "wamid.xxx"
}
JSON · test
{
  "success": true,
  "message_id": "wamid.TEST_xxx",
  "dry_run": true
}

A warnings array appears when the message went out but the channel could not carry part of what you sent — a caption on an Instagram attachment, for instance. The send still succeeded; nothing needs retrying. Log these, because they mean content you supplied never reached the recipient.

JSON · sent with a dropped field
{
  "success": true,
  "message_id": "mid.xxx",
  "warnings": [
    "caption is not supported on Instagram attachments and was not sent — send it as a separate text message if you need it."
  ]
}

Delivery rules to handle

  • Use free-form WhatsApp messages only inside the 24-hour customer-service window; otherwise send an approved template.
  • Serve linked media over public HTTPS with a correct content type and without expiring before Meta downloads it.
  • Honor Retry-After on 429. Do not immediately repeat requests rejected by Meta without correcting the cause.
  • A 402 trial_expired blocks live delivery after trial grace; dry-runs remain available for debugging.
Review errors & debugging
PreviousWebhooks
NextUsage