On this page
Response Formats#
Conversation API responses can be shaped to fit the channel you're delivering them on. Configure the format once per API key in the Console — the same chat agent runs, only the response envelope changes.
markdown and continue to receive the same content/products/actions shape they always have. The only additive change is a new top-level format field on every non-error response — strict schema validators should add it to their parser.Available Formats#
| Format | Use when | Response shape adds |
|---|---|---|
markdown | Web chat UIs, existing integrations | Nothing — today's shape (now with format) |
plain_text | SMS bridges, voice agents, no-UI flows | content is plain text; links flattened to text (url); images dropped |
facebook_messenger | Middleware bridging FB Messenger → your bot → Gydr | elements (≤10), quick_replies (≤13), attachments |
instagram_messaging | Instagram Direct middleware | elements (≤10), quick_replies (≤13), attachments — web_url/postback buttons only, ≤1000-char text |
whatsapp_business | WhatsApp Cloud API middleware | buttons (≤3) OR list (≤10), media_items (≤5), native locations, attachments |
Configuring the Format#
- Go to Console → Settings → Developer
- Create a new API key or edit an existing one — the Response Content Format dropdown unlocks once the
conversations:chatscope is enabled - Pick the format and save
- Changes take effect immediately — the next call to
POST /widgets/{widgetId}/conversations/{sessionId}/messagesuses the new format
Response Examples#
Same agent turn, four shapes. All examples assume the agent returned a couple of product suggestions and a handoff quick reply.
{
"data": {
"messageId": "msg_01HX...",
"format": "markdown",
"content": "Here are two pizzas you might like:\n\n- **Margherita** — RM28\n- **Pepperoni** — RM32\n\nWant me to connect you to staff?",
"products": [
{ "id": "p1", "name": "Margherita", "price": 28, "currency": "MYR", "image": "https://cdn/..." },
{ "id": "p2", "name": "Pepperoni", "price": 32, "currency": "MYR", "image": "https://cdn/..." }
],
"actions": [
{ "label": "Talk to staff", "value": "handoff:zanroo-desk" }
],
"handoff": false,
"sessionEnded": false,
"credits": { "chat": 12, "retrieval": 2, "orchestration": 1, "embedding": 0, "rerank": 1, "plugin": 2, "crawler": 0 },
"usage": { "inputTokens": 482, "outputTokens": 73 }
}
}The credits Field#
Every conversation response carries a credits object alongside usage. It has seven numeric keys — chat, retrieval, orchestration, embedding, rerank, plugin, and crawler — and all seven are always present, so you can read any key without a presence check. A key that did not apply to the turn is 0. What each key meters is documented in How Credits Work.
Breaking change (1.31.0)
The credits.api field was renamed to credits.plugin, and three new buckets were added — retrieval, orchestration, and crawler. If your integration reads credits.api, update it to read credits.plugin.
Mixed Knowledge Base Example (Facebook Messenger)#
When the agent surfaces both products and locations in the same turn, they share the 10-element cap. Products come first, then locations. FAQs and document chunks stay inline in content — they don't produce elements.
{
"data": {
"messageId": "msg_01HX...",
"format": "facebook_messenger",
"content": "Our delivery policy is free over RM50 (FAQ). Two outlets near you are open now.",
"elements": [
{
"title": "Margherita",
"subtitle": "RM28",
"image_url": "https://cdn/margherita.jpg",
"buttons": [{ "type": "web_url", "title": "Order", "url": "https://shop/margherita" }]
},
{
"title": "KL Sentral Outlet",
"subtitle": "Level 2, Nu Sentral, 50470 KL",
"image_url": "https://cdn/outlets/kl-sentral.jpg",
"buttons": [
{ "type": "web_url", "title": "View on map", "url": "https://maps.google.com/?q=3.1349,101.6869" },
{ "type": "phone_number", "title": "Call", "payload": "+60312345678" },
{ "type": "web_url", "title": "Website", "url": "https://example.com/kl-sentral" }
]
},
{
"title": "Bangsar Outlet",
"subtitle": "Jln Maarof, Bangsar, 59100 KL",
"image_url": "https://cdn/outlets/bangsar.jpg",
"buttons": [
{ "type": "web_url", "title": "View on map", "url": "https://maps.google.com/?q=3.1262,101.6724" },
{ "type": "phone_number", "title": "Call", "payload": "+60312345679" }
]
}
],
"products": [ /* ... */ ],
"locations": [ /* still present with full lat/lng */ ],
"actions": [],
"handoff": false,
"sessionEnded": false,
"credits": { /* ... */ },
"usage": { /* ... */ }
}
}Action Protocol (handoff & end-session)#
Quick reply / button payloads round-trip the raw action.value from the agent. When the user taps one, your middleware should POST the payload back to /messages as the content field — the agent recognises the prefix and routes the request:
handoff:<provider>— starts the configured handoff (e.g.handoff:zanroo-desk)end_session:<reason>— ends the session (e.g.end_session:manual)- Any other value — sent as a plain user message
WhatsApp 24-Hour Customer Service Window#
Channel Mapping Reference#
| Gydr field | FB Messenger | WhatsApp Cloud API |
|---|---|---|
| content | Text message body (≤2000 chars, chunked as string[] if longer) | Text body in WA inline syntax (≤4096 chars, chunked similarly) |
| elements | Generic Template carousel elements array (≤10; ≤3 buttons each) | Not directly mapped — use media_items instead |
| quick_replies | quick_replies array (≤13) | Not present — use buttons or list |
| buttons | Not present — use quick_replies or per-element buttons | Interactive reply-buttons (1–3) |
| list | Not present — promote to multi-element or multiple replies | Interactive list message (≤10 rows; auto-promoted when actions > 3) |
| media_items | Map to per-card image + buttons | Send each as image + caption + CTA URL button (≤5) |
| locations | Render as a card with map link + phone button | Native location message type |
| attachments | Image attachment messages | Media messages (image / video / document) |
Instagram Messaging uses the same elements / quick_replies shape as Facebook, with two differences: buttons are web_url/postback only (no phone/Call button — a location's phone is folded into the element subtitle), and the text body is capped at 1000 characters.