curl --request POST \
--url https://api.example.com/api/notifications \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"message": "<string>",
"audience": "<string>",
"channel": "<string>",
"footer": "<string>",
"header": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
},
"location": {
"latitude": 123,
"longitude": 123,
"address": "<string>",
"name": "<string>"
},
"media": [
{
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
],
"options": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"recipient": "<string>",
"schema": {},
"sections": [
{
"rows": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"title": "<string>"
}
],
"sender_identity": "<string>",
"template": {
"language": "<string>",
"name": "<string>",
"body_parameters": [
"<string>"
],
"buttons": [
{
"payload": "<string>",
"kind": "quick_reply"
}
],
"header_media": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
}
}
'import requests
url = "https://api.example.com/api/notifications"
payload = {
"message": "<string>",
"audience": "<string>",
"channel": "<string>",
"footer": "<string>",
"header": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
},
"location": {
"latitude": 123,
"longitude": 123,
"address": "<string>",
"name": "<string>"
},
"media": [
{
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
],
"options": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"recipient": "<string>",
"schema": {},
"sections": [
{
"rows": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"title": "<string>"
}
],
"sender_identity": "<string>",
"template": {
"language": "<string>",
"name": "<string>",
"body_parameters": ["<string>"],
"buttons": [
{
"payload": "<string>",
"kind": "quick_reply"
}
],
"header_media": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
message: '<string>',
audience: '<string>',
channel: '<string>',
footer: '<string>',
header: {url: '<string>', caption: '<string>', filename: '<string>'},
location: {latitude: 123, longitude: 123, address: '<string>', name: '<string>'},
media: [{url: '<string>', caption: '<string>', filename: '<string>'}],
options: [{text: '<string>', description: '<string>', id: '<string>', kind: 'reply'}],
recipient: '<string>',
schema: {},
sections: [
{
rows: [{text: '<string>', description: '<string>', id: '<string>', kind: 'reply'}],
title: '<string>'
}
],
sender_identity: '<string>',
template: {
language: '<string>',
name: '<string>',
body_parameters: ['<string>'],
buttons: [{payload: '<string>', kind: 'quick_reply'}],
header_media: {url: '<string>', caption: '<string>', filename: '<string>'}
}
})
};
fetch('https://api.example.com/api/notifications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/notifications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => '<string>',
'audience' => '<string>',
'channel' => '<string>',
'footer' => '<string>',
'header' => [
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
],
'location' => [
'latitude' => 123,
'longitude' => 123,
'address' => '<string>',
'name' => '<string>'
],
'media' => [
[
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
]
],
'options' => [
[
'text' => '<string>',
'description' => '<string>',
'id' => '<string>',
'kind' => 'reply'
]
],
'recipient' => '<string>',
'schema' => [
],
'sections' => [
[
'rows' => [
[
'text' => '<string>',
'description' => '<string>',
'id' => '<string>',
'kind' => 'reply'
]
],
'title' => '<string>'
]
],
'sender_identity' => '<string>',
'template' => [
'language' => '<string>',
'name' => '<string>',
'body_parameters' => [
'<string>'
],
'buttons' => [
[
'payload' => '<string>',
'kind' => 'quick_reply'
]
],
'header_media' => [
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/notifications"
payload := strings.NewReader("{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/notifications")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/notifications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Send a human a one-way notification
Send a human a one-way notification, fire-and-forget.
No reply is expected and nothing blocks. With a named channel the message is
sent and the call returns as soon as the medium ACCEPTED it (not that a human
saw it). With channel omitted the message is recorded to the internal
notifications sink the Studio inbox reads. One send attempt, no retry; every
failure raises loudly, never a silent no-op:
- a blank message with no media to carry it (the contract admits a blank message
only for a media-only send), an unknown channel name, a blank recipient/audience, a
caller-supplied
sender_identity, a contract-invalidmedia/template/options/schemacombination (an empty list/dict, an over-cap value, or a mutually exclusive media+template / options+template / schema+template / schema+options), aschemawith no channel (the internal sink has no submission door) or one the channel’s form subset/hook refuses, or a channel’s permanent refusal of the input’s shape (retrying cannot succeed) → 400; - a restricted caller addressing another identity (cross-identity denial) → 403;
- a channel that cannot notify, or does not advertise the
media/template/options/schemacapability the send needs → 501; - a transient channel delivery failure (the raised error’s
retryable) → 503, carrying the medium’sretry_afterwhen it named one; - a permanent channel delivery refusal → 502.
media (display media sent with the message), location (a shared map pin),
template (a pre-approved out-of-window send), options (FLAT tappable options a tap
of which enters the conversation), sections (the SECTIONED tappable-options
alternative), header/footer (a media header / trailing line composing an interactive
message) and schema (an ask-less form’s answer schema — the channel renders the
message as the form’s prompt, and a submission enters the conversation as a message from
the person) are OPTIONAL richer-send forms — FULL parity with the flow answer path’s
AnswerPart vocabulary. The contract’s shared composition matrix is enforced on this
request model identically: options XOR sections (one choice surface); schema
excludes both; header/footer require a choice surface; template is the standalone
out-of-window send exclusive with every other content/interactive field; options/
sections may each combine with media/location (a contract-invalid combination is
a 400). On a
named channel each needs a channel that advertises the matching capability
(media→media, location→location, template→template, options/sections→
interactive, schema→form; header/footer ride the choice surface’s capability, no
flag of their own) — otherwise
the send is refused as a 501, never downgraded to a silent freeform send. With no
channel media/location/template/options/sections/header/footer are stored on the internal
inbox record and rendered
there; schema alone REQUIRES a channel (a 400 without one) — a stored form nobody
could submit would be a dead surface, not a notification.
audience addresses the in-app record to an identity’s feed; it is honored
even when a channel also delivers the message (channel push AND in-app record).
sender_identity is the sending identity a channel message leaves FROM, which the
conversation bridge sets on the notification it builds to answer a route; a caller may
not supply it here and a set value is rejected loudly, never forwarded to the channel.
Returns a short confirmation string — "notification sent via '<channel>'"
for a channel send, "notification recorded to the internal sink" otherwise.
curl --request POST \
--url https://api.example.com/api/notifications \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"message": "<string>",
"audience": "<string>",
"channel": "<string>",
"footer": "<string>",
"header": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
},
"location": {
"latitude": 123,
"longitude": 123,
"address": "<string>",
"name": "<string>"
},
"media": [
{
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
],
"options": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"recipient": "<string>",
"schema": {},
"sections": [
{
"rows": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"title": "<string>"
}
],
"sender_identity": "<string>",
"template": {
"language": "<string>",
"name": "<string>",
"body_parameters": [
"<string>"
],
"buttons": [
{
"payload": "<string>",
"kind": "quick_reply"
}
],
"header_media": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
}
}
'import requests
url = "https://api.example.com/api/notifications"
payload = {
"message": "<string>",
"audience": "<string>",
"channel": "<string>",
"footer": "<string>",
"header": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
},
"location": {
"latitude": 123,
"longitude": 123,
"address": "<string>",
"name": "<string>"
},
"media": [
{
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
],
"options": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"recipient": "<string>",
"schema": {},
"sections": [
{
"rows": [
{
"text": "<string>",
"description": "<string>",
"id": "<string>",
"kind": "reply"
}
],
"title": "<string>"
}
],
"sender_identity": "<string>",
"template": {
"language": "<string>",
"name": "<string>",
"body_parameters": ["<string>"],
"buttons": [
{
"payload": "<string>",
"kind": "quick_reply"
}
],
"header_media": {
"url": "<string>",
"caption": "<string>",
"filename": "<string>"
}
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
message: '<string>',
audience: '<string>',
channel: '<string>',
footer: '<string>',
header: {url: '<string>', caption: '<string>', filename: '<string>'},
location: {latitude: 123, longitude: 123, address: '<string>', name: '<string>'},
media: [{url: '<string>', caption: '<string>', filename: '<string>'}],
options: [{text: '<string>', description: '<string>', id: '<string>', kind: 'reply'}],
recipient: '<string>',
schema: {},
sections: [
{
rows: [{text: '<string>', description: '<string>', id: '<string>', kind: 'reply'}],
title: '<string>'
}
],
sender_identity: '<string>',
template: {
language: '<string>',
name: '<string>',
body_parameters: ['<string>'],
buttons: [{payload: '<string>', kind: 'quick_reply'}],
header_media: {url: '<string>', caption: '<string>', filename: '<string>'}
}
})
};
fetch('https://api.example.com/api/notifications', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/notifications",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'message' => '<string>',
'audience' => '<string>',
'channel' => '<string>',
'footer' => '<string>',
'header' => [
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
],
'location' => [
'latitude' => 123,
'longitude' => 123,
'address' => '<string>',
'name' => '<string>'
],
'media' => [
[
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
]
],
'options' => [
[
'text' => '<string>',
'description' => '<string>',
'id' => '<string>',
'kind' => 'reply'
]
],
'recipient' => '<string>',
'schema' => [
],
'sections' => [
[
'rows' => [
[
'text' => '<string>',
'description' => '<string>',
'id' => '<string>',
'kind' => 'reply'
]
],
'title' => '<string>'
]
],
'sender_identity' => '<string>',
'template' => [
'language' => '<string>',
'name' => '<string>',
'body_parameters' => [
'<string>'
],
'buttons' => [
[
'payload' => '<string>',
'kind' => 'quick_reply'
]
],
'header_media' => [
'url' => '<string>',
'caption' => '<string>',
'filename' => '<string>'
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/notifications"
payload := strings.NewReader("{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/api/notifications")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/notifications")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"message\": \"<string>\",\n \"audience\": \"<string>\",\n \"channel\": \"<string>\",\n \"footer\": \"<string>\",\n \"header\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n },\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123,\n \"address\": \"<string>\",\n \"name\": \"<string>\"\n },\n \"media\": [\n {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n ],\n \"options\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"recipient\": \"<string>\",\n \"schema\": {},\n \"sections\": [\n {\n \"rows\": [\n {\n \"text\": \"<string>\",\n \"description\": \"<string>\",\n \"id\": \"<string>\",\n \"kind\": \"reply\"\n }\n ],\n \"title\": \"<string>\"\n }\n ],\n \"sender_identity\": \"<string>\",\n \"template\": {\n \"language\": \"<string>\",\n \"name\": \"<string>\",\n \"body_parameters\": [\n \"<string>\"\n ],\n \"buttons\": [\n {\n \"payload\": \"<string>\",\n \"kind\": \"quick_reply\"\n }\n ],\n \"header_media\": {\n \"url\": \"<string>\",\n \"caption\": \"<string>\",\n \"filename\": \"<string>\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Authorizations
Body
A notification to send: the message text, an optional named channel
that carries it (omit to record to the internal sink), an optional per-call
recipient delivery address, and an optional audience identity whose in-app
inbox shows it (honored even with a channel set; distinct from recipient).
The identity (user_id) whose in-app inbox shows this (honored even with a channel set); leave unset for an operator/broadcast notification. Distinct from recipient, which is a channel delivery address.
Optional short trailing line under an interactive message. Like the header it COMPOSES an interactive message, so it REQUIRES options or sections; it rides the choice surface's own capability (no separate flag) and mutually exclusive with template.
Optional single display-media header above an interactive message. It COMPOSES an interactive message, so it REQUIRES options or sections; it rides the interactive choice surface's own capability (no separate flag) and mutually exclusive with template.
Show child attributes
Show child attributes
Optional shared geographic point sent WITH the message (a map pin). On a named channel it requires a channel that advertises location support (else a 501); with no channel it is stored on the internal inbox record. It may carry the message content on its own (a blank message is admissible when media or a location carries it). Mutually exclusive with template.
Show child attributes
Show child attributes
Optional display media sent WITH the message. On a named channel it requires a channel that advertises media support (else a 501); with no channel it is stored on the internal inbox record and rendered there. Mutually exclusive with template.
Show child attributes
Show child attributes
Optional FLAT tappable options sent WITH the message — each a reply option (a tap submits its text as a visitor message) or a link option (a tap opens its url). On a named channel it requires a channel that advertises interactive support (else a 501); with no channel it is stored on the internal inbox record. One message carries ONE interactive surface: mutually exclusive with template, sections and schema; may combine with media and location.
A tappable suggested reply. Tapping SUBMITS text as the participant's next inbound message —
the quick-reply / list-row case, where the option's own text becomes the turn. description
is an OPTIONAL secondary line a sectioned-list row renders under its text; a channel that
renders flat buttons (no descriptions) ignores it.
id is an OPTIONAL author-set stable identifier for the button/list row. When set, a channel
sends it verbatim on the wire and the participant's tap echoes it back (a channel surfaces the echoed
id to the inbound turn as opaque enrichment — e.g. Slack forwards it as params.reply_id);
when None the channel mints its own id as today. Bounded by OPTION_ID_MAX_CHARS and a
single-line non-blank label — the strictest carrier's rule. Frozen.
- ReplyOption
- LinkOption
Show child attributes
Show child attributes
Optional form answer schema for an ask-less form: the channel renders the message as the form's prompt and this schema as the fillable form, and a submission enters the conversation as a message from the person. Requires a named channel (else a 400 — the internal sink has no submission door) that advertises form support (else a 501). Mutually exclusive with template and with options, may combine with media.
Optional SECTIONED tappable options — titled groups of reply rows, the sectioned alternative to the flat options list (rows summed across sections stay within the same cap). On a named channel it requires a channel that advertises interactive support (else a 501); with no channel it is stored on the internal inbox record. One message carries ONE interactive surface: mutually exclusive with options, template and schema; may combine with media and location.
Show child attributes
Show child attributes
Reserved: the sending identity a channel message leaves FROM, set by the conversation bridge on the notification it builds to answer a route. Callers MUST NOT supply it here — a set value is rejected with a 400, never forwarded.
Optional pre-approved template for an out-of-window send. On a named channel it requires a channel that advertises template support (else a 501); with no channel it is stored on the internal inbox record. Mutually exclusive with media and options.
Show child attributes
Show child attributes
Response
Success.
The notify-user body: a bare confirmation STRING (the adapter envelopes it
as {"data": <str>}). Typed as a string rather than wrapped, so the wire
body is unchanged.

