Skip to content
Conversation API

Response Formats

Configure response shape per API key — Markdown, plain text, Messenger, WhatsApp, or Instagram.

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.

Backward compatible. Existing keys default to 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#

FormatUse whenResponse shape adds
markdownWeb chat UIs, existing integrationsNothing — today's shape (now with format)
plain_textSMS bridges, voice agents, no-UI flowscontent is plain text; links flattened to text (url); images dropped
facebook_messengerMiddleware bridging FB Messenger → your bot → Gydrelements (≤10), quick_replies (≤13), attachments
instagram_messagingInstagram Direct middlewareelements (≤10), quick_replies (≤13), attachments — web_url/postback buttons only, ≤1000-char text
whatsapp_businessWhatsApp Cloud API middlewarebuttons (≤3) OR list (≤10), media_items (≤5), native locations, attachments

Configuring the Format#

  1. Go to Console → Settings → Developer
  2. Create a new API key or edit an existing one — the Response Content Format dropdown unlocks once the conversations:chat scope is enabled
  3. Pick the format and save
  4. Changes take effect immediately — the next call to POST /widgets/{widgetId}/conversations/{sessionId}/messages uses 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#

Your middleware's responsibility. WhatsApp Cloud API only permits free-form responses within 24 hours of the user's last inbound message. Outside that window you must use a pre-approved template. Track the inbound timestamp at your bridge and gate outbound delivery accordingly — Gydr returns the same response shape regardless.

Channel Mapping Reference#

Gydr fieldFB MessengerWhatsApp Cloud API
contentText message body (≤2000 chars, chunked as string[] if longer)Text body in WA inline syntax (≤4096 chars, chunked similarly)
elementsGeneric Template carousel elements array (≤10; ≤3 buttons each)Not directly mapped — use media_items instead
quick_repliesquick_replies array (≤13)Not present — use buttons or list
buttonsNot present — use quick_replies or per-element buttonsInteractive reply-buttons (1–3)
listNot present — promote to multi-element or multiple repliesInteractive list message (≤10 rows; auto-promoted when actions > 3)
media_itemsMap to per-card image + buttonsSend each as image + caption + CTA URL button (≤5)
locationsRender as a card with map link + phone buttonNative location message type
attachmentsImage attachment messagesMedia 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.

We use cookies to run and improve Gydr.

Read our Cookie Policy