Zernio
Zernio
PlatformsRCSRegistering an agentSendingReceiving
Dashboard
llms.txtOpenAPI
OverviewPlatformsAPI ReferenceResources
RCS

Sending

Send RCS text, media, rich cards and carousels with buttons from your agent with POST /v1/rcs/messages, with SMS fallback for phones without RCS.


When you finish this page you have sent every kind of RCS message and know what happens on phones that cannot receive RCS. You need an agent in testing (to reach your accepted test phones) or live (to reach anyone). See registering an agent.

Step 1: Send a text with buttons

Call POST /v1/rcs/messages with agentId, to and either text (a plain message) or content (anything richer). This example sends text with three buttons.

curl -X POST "https://zernio.com/api/v1/rcs/messages" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-4821-shipped" \
  -d '{
    "agentId": "6aba8af3e7aba406647e82a1",
    "to": "+13125550188",
    "content": {
      "type": "text",
      "text": "Your order #4821 has shipped. It arrives Thursday between 10:00 and 14:00.",
      "suggestions": [
        { "type": "openUrl", "text": "Track package", "url": "https://northsideshoes.example.com/t/4821" },
        { "type": "calendarEvent", "text": "Add to calendar", "startTime": "2027-01-07T10:00:00Z", "endTime": "2027-01-07T14:00:00Z", "title": "Northside Shoes delivery" },
        { "type": "reply", "text": "Change address", "postbackData": "change_address_4821" }
      ]
    },
    "fallbackText": "Northside Shoes: order #4821 shipped, arriving Thursday. Track it: https://northsideshoes.example.com/t/4821"
  }'

Response (200):

{
  "id": "4031938e-60e4-4235-a8dd-0b1c55a23e7a",
  "conversationId": "66c3d2ae7b4f6c8d0e1f2a3c",
  "status": "sent"
}

The message threads into the agent's inbox conversation with that phone number, and its delivery and read receipts arrive as webhooks (see receiving). Send an Idempotency-Key header so a retry replays the original response instead of sending twice (idempotency).

Step 2: Send rich content

content.type picks the layout. Every type accepts up to 11 suggestions shown under the message.

Media: an image or video on its own.

{ "type": "media", "media": { "url": "https://northsideshoes.example.com/img/trail-runner.jpg" } }

Rich card: media, a title up to 200 characters, a description up to 2,000 and up to 4 buttons on the card. orientation is VERTICAL (default) or HORIZONTAL, and media.height is SHORT, MEDIUM (default) or TALL.

{
  "type": "card",
  "card": {
    "title": "Trail Runner 2",
    "description": "20% off this weekend with code TRAIL20. Free returns for 60 days.",
    "media": { "url": "https://northsideshoes.example.com/img/trail-runner.jpg", "height": "MEDIUM" },
    "suggestions": [
      { "type": "openUrl", "text": "Shop now", "url": "https://northsideshoes.example.com/trail" },
      { "type": "reply", "text": "Not interested", "postbackData": "optout_promo" }
    ]
  }
}

Carousel: 2 to 10 cards the person swipes through. cardWidth is SMALL or MEDIUM (default).

{
  "type": "carousel",
  "cards": [
    { "title": "City Knit", "description": "$89, 6 colours", "media": { "url": "https://northsideshoes.example.com/img/city-knit.jpg" } },
    { "title": "Trail Runner 2", "description": "$120, waterproof", "media": { "url": "https://northsideshoes.example.com/img/trail.jpg" } }
  ]
}

Buttons

typeWhat a tap doesExtra fields
replySends the label back as a replypostbackData
openUrlOpens a linkurl, optional application (BROWSER or WEBVIEW) and webviewViewMode (FULL, HALF, TALL)
dialStarts a callphoneNumber (E.164)
viewLocationOpens the map on a pinlatitude, longitude, optional label
shareLocationAsks the person to share their locationnone
calendarEventAdds an event to their calendarstartTime, endTime, title (100), optional description (500)

Button labels are up to 25 characters. postbackData is up to 2,048 characters of any string, JSON included, and comes back unchanged when the button is tapped; it defaults to the label.

SMS fallback

If the agent has smsFallbackFrom set, phones that cannot receive RCS get the message as plain SMS from that number: fallbackText when you send it, otherwise the message's text (for cards, the title, description and media link). Without a fallback number the message only reaches RCS phones. Add ttlSeconds to let an undelivered message expire after that many seconds.

To check ahead of time which recipients can receive RCS, and which rich features their phones support, call GET /v1/rcs/capabilities with up to 100 numbers:

curl "https://zernio.com/api/v1/rcs/capabilities?agentId=6aba8af3e7aba406647e82a1&numbers=%2B13125550188,%2B13125550177" \
  -H "Authorization: Bearer $ZERNIO_API_KEY"

Response (200):

{
  "capabilities": [
    { "phoneNumber": "+13125550188", "rcsCapable": true, "features": ["RICHCARD_STANDALONE", "RICHCARD_CAROUSEL", "ACTION_OPEN_URL", "ACTION_DIAL"] },
    { "phoneNumber": "+13125550177", "rcsCapable": false }
  ]
}

If it fails

A 403 means the agent is not launched yet and the number is not an accepted test phone (the message says so). A 409 means the recipient opted out (code recipient_opted_out), or the agent does not exist with the carriers yet (invalid_resource_state). A 404 means the agent is not on your team. Every error uses the envelope in error handling.

Related

  • Receiving: replies, button taps and receipts.
  • Registering an agent: test phones and the SMS fallback number.
Was this page helpful?

Registering an agent

Create an RCS brand and agent with POST /v1/rcs/agents, answer our review, test on your own phones and send the launch details to the carriers.

Receiving

RCS replies, button taps, shared locations and files arrive in the inbox as platform rcs, with message.received, message.delivered, message.read and message.failed webhooks.

On this page

Step 1: Send a text with buttonsStep 2: Send rich contentButtonsSMS fallbackIf it failsRelated