Messages & Blocks
Relay messages are envelopes with ordered content blocks. Durable transcript content lives in content. Typing, receipts, reactions, and live status move as events around the message instead of fake transcript rows.
Envelope
Section titled “Envelope”{ "schema": "relay.message.v1", "id": "msg_01JZ7S8D9R0A", "conversationId": "conv_trip", "sender": { "kind": "agent", "id": "agent_travel", "displayName": "Travel" }, "role": "agent", "direction": "inbound", "createdAt": "2026-07-06T16:20:00Z", "revision": 1, "status": "sent", "fallbackText": "I found two flight options and need your approval to book.", "content": [ { "id": "blk_summary", "type": "text", "text": "I found two flight options under your target price." }, { "id": "blk_options", "type": "actions", "layout": "quick_replies", "actions": [ { "actionId": "act_show_options", "label": "Show options", "style": "primary", "behavior": { "type": "postback", "value": "show_flight_options" } } ] } ]}contentis an ordered array.- Every block has a stable
id. - Every message has
fallbackTextfor notifications, search, accessibility, and older clients. - Button actions use IDs, not labels.
- Unsupported blocks downgrade to fallback text.
- V1 blocks render as native SwiftUI primitives, not webviews.
{ "id": "blk_text_1", "type": "text", "text": "Dinner is booked for 7:30 PM.", "entities": [ { "type": "phone", "range": { "start": 0, "length": 0 }, "value": "+12125550123" } ]}{ "id": "blk_image_1", "type": "image", "asset": { "url": "https://cdn.relay.app/attachments/img_123.png", "mimeType": "image/png", "width": 1600, "height": 1200, "sizeBytes": 482102, "thumbnailUrl": "https://cdn.relay.app/attachments/img_123_thumb.jpg" }, "altText": "A hotel room with a desk facing the window.", "caption": "Room option from the hotel listing.", "presentation": "inline"}File Card
Section titled “File Card”{ "id": "blk_file_1", "type": "file", "file": { "id": "file_invoice_123", "name": "Invoice-1842.pdf", "mimeType": "application/pdf", "sizeBytes": 248120, "icon": "pdf", "downloadUrl": "https://cdn.relay.app/files/invoice-1842.pdf", "checksum": "sha256:7a7d..." }, "preview": { "type": "pdf", "thumbnail": { "url": "https://cdn.relay.app/files/invoice-1842-page1.jpg", "mimeType": "image/jpeg", "width": 612, "height": 792 }, "pageCount": 2 }, "actions": [ { "actionId": "act_download_invoice", "label": "Download", "behavior": { "type": "download_file", "fileId": "file_invoice_123", "url": "https://cdn.relay.app/files/invoice-1842.pdf" } } ]}Link Preview
Section titled “Link Preview”{ "id": "blk_link_1", "type": "link_preview", "url": "https://example.com/listing/42", "canonicalUrl": "https://example.com/listing/42", "title": "Modern apartment near Union Square", "description": "Two bedrooms, in-unit laundry, available August 1.", "siteName": "Example Homes", "faviconUrl": "https://example.com/favicon.ico", "image": { "url": "https://example.com/listing/42/cover.jpg", "mimeType": "image/jpeg", "width": 1200, "height": 630 }}{ "id": "blk_card_1", "type": "card", "title": "Delta 2481", "subtitle": "Detroit to New York, 7:40 PM", "body": "Refundable main cabin fare. Seat 14A is available.", "image": { "url": "https://cdn.relay.app/cards/delta-2481.png", "mimeType": "image/png", "width": 1200, "height": 630 }, "badges": [ { "text": "Refundable", "tone": "success" }, { "text": "Under budget", "tone": "info" } ], "fields": [ { "label": "Total", "value": "$412.18" }, { "label": "Arrives", "value": "10:15 PM" } ], "actions": [ { "actionId": "act_view_flight", "label": "View", "behavior": { "type": "open_url", "url": "https://relay.app/flights/quote_123" } } ]}Buttons
Section titled “Buttons”Buttons are the actions block. Use layout: "quick_replies" for iMessage-style reply chips and layout: "button_row" for command buttons.
{ "id": "blk_quick_replies_1", "type": "actions", "layout": "quick_replies", "actions": [ { "actionId": "act_yes", "label": "Yes", "style": "primary", "behavior": { "type": "send_text", "text": "Yes" } }, { "actionId": "act_no", "label": "No", "behavior": { "type": "send_text", "text": "No" } }, { "actionId": "act_more", "label": "Show more", "behavior": { "type": "postback", "value": "show_more_options", "data": { "source": "flight_search" } } } ]}Call Event
Section titled “Call Event”{ "id": "blk_call_1", "type": "call_event", "callId": "call_abc123", "callType": "voice", "event": "ended", "startedAt": "2026-07-06T16:00:00Z", "endedAt": "2026-07-06T16:07:34Z", "durationMs": 454000, "participants": [ { "kind": "user", "id": "user_advait", "displayName": "Advait" }, { "kind": "agent", "id": "agent_scheduler", "displayName": "Scheduler" } ], "fallbackText": "Voice call ended after 7 minutes."}Downgrades
Section titled “Downgrades”When a client cannot render a block type, Relay renders block.fallbackText when present. Otherwise it generates a fallback from block fields:
| Block | Generated fallback |
|---|---|
image |
Image: {caption or altText} |
file |
{name}, {formatted size} |
link_preview |
{title} - {url} |
card |
{title}: {subtitle} |
actions |
Message fallback plus supported actions |
call_event |
{Voice or Video} call {event} |