Chimes
Chimes let you send notification messages to customers by SMS or email. Use them for receipts, order updates, reminders, and other customer communication that is not part of an authentication flow. For one-time passwords, use the OTP API instead.
The Chime object
A Chime represents one notification sent to one recipient. It stores the message body, recipient details, sender, optional customer reference, and transmission status so you can see exactly what was sent and what happened after delivery was attempted.
Properties
Stored message template references
Chime send, schedule, and broadcast requests can render a stored message template instead of accepting inline content. Use this shape when the content should come from a published reusable template:
{
"message_template": {
"template_id": "mtpl_receipt_ready",
"variables": {
"customer_name": "Gloria",
"receipt_url": "https://yourstore.example/receipts/or_123"
}
}
}
message_template.template_id must identify an active template owned by the authenticated application. message_template.variables must satisfy the template's published variable contract. The rendered template channel must match the resolved recipient transport: SMS templates can send only to SMS recipients, and email templates can send only to email recipients.
Provide exactly one content source for the resolved transport. For SMS sends and schedules, use either full_message or an SMS message_template; for SMS broadcasts, use message_template as either raw SMS text or a stored template object. For email sends, schedules, and broadcasts, use either email or an email message_template. Do not combine SMS content and email content in the same request.
Use Render a message template preview before sending production campaigns when variable values come from user or catalog data.
Send Chime
Send one notification immediately. You can address it directly with a phone number or email address, or point to a saved customer and let Commerce use that customer's phone number or email address.
Rules
- Phone/SMS recipients require exactly one SMS content source:
full_messageormessage_template. - Email recipients require exactly one email content source:
emailormessage_template. - Do not mix SMS and email content in one Send Chime request.
- Email content must include
subject,text, andfrom.address. Optional HTML and headers are safety-scanned before delivery. - Stored templates must match the resolved recipient transport. SMS recipients require an SMS template; email recipients require an email template.
recipientmust use exactly one of two shapes: inline recipient (typeplus matchingphone.numberoremail.address) or saved customer (transportpluscustomer_id).recipientcannot include bothtypeandtransport.- Inline recipients cannot include
customer_id.
Required attributes
Optional attributes
Email attributes
To send a Chime to a saved customer, pass recipient.customer_id and choose which contact method to use:
{
"recipient": {
"customer_id": "cu_abc123def456",
"transport": "sms"
},
"full_message": "Your order has shipped."
}
To send email to an inline address, use recipient.type: "email" and include the top-level email object:
{
"recipient": {
"type": "email",
"email": {
"address": "[email protected]"
},
"name": "Gloria Kesewaa"
},
"email": {
"subject": "Your receipt from YourBrand",
"text": "Your receipt is ready. View it at https://yourbrand.example/receipts/or_123.",
"html": "<p>Your receipt is ready. <a href=\"https://yourbrand.example/receipts/or_123\">View receipt</a>.</p>",
"from": {
"name": "YourBrand",
"address": "[email protected]"
}
},
"purpose": "receipt"
}
To send with a stored template, use the generated template ID and keep variables inside the message_template object:
{
"recipient": {
"customer_id": "cu_abc123def456",
"transport": "sms"
},
"message_template": {
"template_id": "mtpl_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
"variables": {
"order_number": "OR-12345",
"tracking_url": "https://track.example.com/OR-12345"
}
}
}
The examples below use the saved-customer shape. If you want to address someone directly instead, replace transport and customer_id with type and the matching inline phone or email details.
Request
curl https://api.zebo.dev/chimes/send \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_meta": {
"idempotency_key": "chime_ship_or_abc123"
},
"recipient": {
"customer_id": "cu_abc123def456",
"transport": "sms"
},
"full_message": "Your order #OR-12345 has been shipped and will arrive in 2-3 business days.",
"sender_id": "YourBrand",
"purpose": "shipping_update",
"custom_data": {
"order_id": "or_abc123",
"fulfillment_id": "ffl_xyz789"
}
}'
{
"chime": {
"id": "ch_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
"customer_id": "cu_abc123def456",
"created_at": "2025-12-10T10:30:00Z",
"full_message": "Your order #OR-12345 has been shipped and will arrive in 2-3 business days. Track at: https://track.example.com/OR-12345",
"recipient": {
"type": "phone",
"phone": {
"number": "+233544998605"
},
"name": "Gloria Kesewaa"
},
"sender_id": "YourBrand",
"purpose": "shipping_update",
"custom_data": {
"order_id": "or_abc123",
"fulfillment_id": "ffl_xyz789"
},
"transmission": {
"created_at": "2025-12-10T10:30:00Z",
"sent_via": "sms",
"status": "sent",
"sent_at": "2025-12-10T10:30:05Z",
"delivered_at": null,
"failed_at": null
}
}
}
Lookup Chime
Retrieve the complete details of a previously sent Chime by its ID. Returns the full Chime object including transmission status and all custom data you attached during creation. Use this endpoint to track message delivery, verify sends during support requests, and reconcile Chimes with your internal systems.
Required attributes
Request
curl https://api.zebo.dev/chimes/lookup \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"chime_id": "ch_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU"
}'
{
"chime": {
"id": "ch_WkPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYU",
"created_at": "2025-12-10T10:30:00Z",
"full_message": "Your order #OR-12345 has been shipped and will arrive in 2-3 business days. Track at: https://track.example.com/OR-12345",
"recipient": {
"type": "phone",
"phone": {
"number": "+233544998605"
},
"name": "John Doe"
},
"sender_id": "YourBrand",
"purpose": "shipping_update",
"custom_data": {
"order_id": "or_abc123",
"fulfillment_id": "ffl_xyz789"
},
"transmission": {
"created_at": "2025-12-10T10:30:00Z",
"sent_via": "sms",
"status": "delivered",
"sent_at": "2025-12-10T10:30:05Z",
"delivered_at": "2025-12-10T10:30:15Z",
"failed_at": null
}
}
}
Page Chimes
Retrieve a page of Chimes for the authenticated application. Results are sorted by created_at in descending order so page 1 contains the newest activity first.
Optional attributes
You can filter by recipient, customer_id, both, or neither.
The response size is the number of Chimes actually returned in chimes,
not the requested page capacity.
Request
curl https://api.zebo.dev/chimes/page -H "Authorization: Bearer $COMMERCE_API_KEY" -H "Content-Type: application/json" -d '{
"page_number": 1,
"page_size": 25,
"customer_id": "cu_abc123def456"
}'
Schedule Chime
Schedule one notification or a batch of notifications for future delivery. Each recipient can either describe an inline phone or email contact, or reference a saved customer.
Rules
send_afterandrecipientsare required.- All recipients in one schedule must resolve to the same transport: SMS or email.
- SMS schedules require exactly one SMS content source:
full_messageormessage_template. - Email schedules require exactly one email content source:
emailormessage_template. - Do not mix SMS and email content in one schedule.
- Stored templates must match the resolved recipient transport.
- Each recipient must use exactly one of two shapes: inline recipient (
typeplus matchingphone.numberoremail.address) or saved customer (transportpluscustomer_id). - A recipient cannot include both
typeandtransport. send_aftermust be in the future.
Required attributes
Optional attributes
To schedule for saved customers, include recipients with customer_id and transport:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "sms" },
{ "customer_id": "cu_def456ghi789", "transport": "sms" }
],
"full_message": "Reminder: Your appointment starts tomorrow at 10 AM.",
"send_after": "2025-12-15T10:00:00Z",
"request_meta": {
"idempotency_key": "sched_appointment_cu_abc123_2025_12_15"
}
}
To schedule email for saved customers, set transport: "email" and provide the top-level email object:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "email" },
{ "customer_id": "cu_def456ghi789", "transport": "email" }
],
"email": {
"subject": "Your subscription renews tomorrow",
"text": "Your subscription renews tomorrow. Update billing at https://yourbrand.example/billing.",
"from": {
"address": "[email protected]"
}
},
"send_after": "2025-12-15T10:00:00Z",
"purpose": "reminder"
}
To schedule with a stored template, use the same message_template object shape used by Send Chime:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "email" }
],
"message_template": {
"template_id": "mtpl_emailRenewal123",
"variables": {
"customer_name": "Gloria",
"renewal_date": "2025-12-16"
}
},
"send_after": "2025-12-15T10:00:00Z",
"purpose": "reminder"
}
The examples below mix both recipient shapes in the same request.
Request
curl https://api.zebo.dev/chimes/schedule \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{
"customer_id": "cu_abc123def456",
"transport": "sms"
},
{
"type": "phone",
"phone": {
"number": "+233501234567"
},
"name": "Backup Contact"
}
],
"full_message": "Reminder: Your subscription renews tomorrow. Visit https://example.com/billing to update payment details.",
"send_after": "2025-12-15T09:00:00Z",
"sender_id": "YourBrand",
"purpose": "reminder"
}'
{
"scheduled_chime": {
"id": "sch_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"created_at": "2025-12-10T14:30:00Z",
"customer_ids": [
"cu_abc123def456"
],
"recipients": [
"+233544998605",
"+233501234567"
],
"full_message": "Reminder: Your subscription renews tomorrow. Visit https://example.com/billing to update payment details.",
"sender_id": "YourBrand",
"purpose": "reminder",
"send_after": "2025-12-15T09:00:00Z"
}
}
Lookup a scheduled Chime
Retrieve a scheduled Chime and check its execution status. Returns the schedule details, IDs of all Chimes created when it executed, and any delivery failures. Use this to track broadcast delivery success, debug failed recipients, or verify cancellation status.
Required attributes
Response attributes
Request
curl https://api.zebo.dev/schedules/lookup \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"schedule_id": "sch_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk"
}'
{
"scheduled_chime": {
"id": "sch_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"recipients": [
"+233544998605",
"+233501234567",
"+233509999999"
],
"content": "Reminder: Your subscription renews tomorrow. Visit https://example.com/billing to update payment details.",
"sender_id": "YourBrand",
"purpose": "reminder",
"send_after": "2025-12-15T09:00:00Z",
"created_at": "2025-12-10T14:30:00Z",
"executed_at": "2025-12-15T09:00:03Z",
"chime_ids": [
"ch_abc123xyz",
"ch_def456uvw"
],
"errors": [
{
"recipient": "[email protected]",
"type": "recipient_unreachable",
"fix_code": "f-change_request_parameters"
}
]
}
}
Cancel a scheduled Chime
Cancel a pending scheduled Chime before it executes. Prevents message delivery if called before the send_after time. Returns an error if the schedule already executed or was previously canceled. A retry is safe only when it reuses the same Idempotency-Key; a new cancellation request after cancellation returns an error.
Rules
- Only works on pending schedules (not yet executed)
- Cannot cancel after
executed_atis set - Cannot cancel schedules that are already canceled
Required attributes
Request
curl https://api.zebo.dev/schedules/cancel \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cancel-schedule-kPvqTrqGsopu07wf" \
-d '{
"schedule_id": "sch_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk"
}'
{
"scheduled_chime": {
"id": "sch_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"customer_ids": [
"cu_abc123def456"
],
"recipients": [
"+233544998605",
"+233501234567"
],
"content": "Reminder: Your subscription renews tomorrow. Visit https://example.com/billing to update payment details.",
"sender_id": "YourBrand",
"purpose": "reminder",
"send_after": "2025-12-15T09:00:00Z",
"created_at": "2025-12-10T14:30:00Z",
"canceled_at": "2025-12-14T16:45:00Z"
}
}
Broadcast Chimes
Send one message immediately to many recipients. Use this for announcements, updates, or any notification that should go out now to a whole audience.
Rules
recipientsis required.senderis optional, but providing it is strongly recommended. The API does not apply a default when it is omitted.- All recipients in one broadcast must resolve to the same transport: SMS or email.
- SMS broadcasts require
message_template, either as a raw SMS string or a stored template object. - Email broadcasts require exactly one email content source:
emailor a storedmessage_templateobject. - Do not mix SMS and email content in one broadcast.
- Stored templates must match the resolved recipient transport.
- Each recipient must use exactly one of two shapes: inline recipient (
typeplus matchingphone.numberoremail.address) or saved customer (transportpluscustomer_id). - A recipient cannot include both
typeandtransport. - Each recipient receives an individual Chime.
Required attributes
Optional attributes
For SMS broadcasts, message_template may be a raw SMS string for legacy inline content or an object with template_id and variables for stored templates. For email broadcasts, message_template must be an object; raw string content is SMS-only.
To broadcast to saved customers, include recipients with customer_id and transport:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "email" },
{ "customer_id": "cu_def456ghi789", "transport": "email" }
],
"email": {
"subject": "Your order has shipped",
"text": "Your order has shipped. Track it at https://track.shop.example/abc123.",
"from": {
"address": "[email protected]"
}
},
"sender": "ShopBrand",
"request_meta": {
"idempotency_key": "broadcast_shipping_2025_12_15"
}
}
To broadcast an email-only campaign, use email recipients and provide the top-level email object:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "email" },
{
"type": "email",
"email": {
"address": "[email protected]"
},
"name": "Backup Contact"
}
],
"email": {
"subject": "Your order has shipped",
"text": "Your order #12345 has shipped. Track it at https://track.shop.example/abc123.",
"from": {
"address": "[email protected]"
}
},
"sender": "ShopBrand",
"purpose": "order_notification"
}
To broadcast with a stored template, pass message_template as an object:
{
"recipients": [
{ "customer_id": "cu_abc123def456", "transport": "email" },
{ "customer_id": "cu_def456ghi789", "transport": "email" }
],
"message_template": {
"template_id": "mtpl_emailShipping123",
"variables": {
"order_number": "OR-12345",
"tracking_url": "https://track.shop.example/OR-12345"
}
},
"sender": "ShopBrand",
"purpose": "order_notification"
}
The examples below mix both recipient shapes in the same request.
Request
curl https://api.zebo.dev/chimes/broadcast \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{
"customer_id": "cu_abc123def456",
"transport": "email"
},
{
"type": "email",
"email": {
"address": "[email protected]"
},
"name": "Backup Contact"
}
],
"email": {
"subject": "Your order #12345 has shipped",
"text": "Your order #12345 has shipped. Track it at https://track.shop.com/abc123.",
"from": {
"address": "[email protected]"
}
},
"sender": "ShopName",
"purpose": "order_notification"
}'
{
"broadcast": {
"id": "brc_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"customer_ids": [
"cu_abc123def456"
],
"recipients": [
"[email protected]",
"[email protected]"
],
"email": {
"subject": "Your order #12345 has shipped",
"text": "Your order #12345 has shipped. Track it at https://track.shop.com/abc123.",
"from": {
"address": "[email protected]"
}
},
"sender_id": "ShopName",
"purpose": "order_notification",
"send_after": "2025-12-15T09:00:00Z",
"created_at": "2025-12-15T09:00:00Z"
}
}
Lookup a broadcast
Retrieve a broadcast and check its execution status. Returns the broadcast details, IDs of all Chimes created when it executed, and any delivery failures. Use this to track delivery success, debug failed recipients, or verify cancellation status.
Required attributes
Response attributes
Request
curl https://api.zebo.dev/broadcasts/lookup \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"broadcast_id": "brc_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk"
}'
{
"broadcast": {
"id": "brc_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"customer_ids": [
"cu_abc123def456"
],
"recipients": [
"[email protected]",
"[email protected]",
"[email protected]"
],
"content": "Your order #12345 has shipped! Track: https://track.shop.com/abc123",
"sender_id": "ShopName",
"purpose": "order_notification",
"send_after": "2025-12-15T09:00:00Z",
"created_at": "2025-12-15T09:00:00Z",
"executed_at": "2025-12-15T09:00:03Z",
"chime_ids": [
"ch_abc123xyz",
"ch_def456uvw"
],
"errors": [
{
"recipient": "[email protected]",
"type": "recipient_unreachable",
"fix_code": "f-change_request_parameters"
}
]
}
}
Cancel a broadcast
Cancel a pending broadcast before it executes. Since broadcasts execute within seconds, cancellation only works if called immediately after creation. Returns an error if the broadcast already executed or was previously canceled. A retry is safe only when it reuses the same Idempotency-Key; a new cancellation request after cancellation returns an error.
Rules
- Only works on pending broadcasts (not yet executed)
- Cannot cancel after
executed_atis set - Cannot cancel broadcasts that are already canceled
- Narrow time window (typically <5 seconds)
Required attributes
Request
curl https://api.zebo.dev/broadcasts/cancel \
-H "Authorization: Bearer $COMMERCE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cancel-broadcast-kPvqTrqGsopu07wf" \
-d '{
"broadcast_id": "brc_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk"
}'
{
"broadcast": {
"id": "brc_kPvqTrqGsopu07wfC7ttoWqmfwt48ZW7BGvYUWk",
"recipients": [
"+233544998605",
"+233501234567"
],
"content": "Your order #12345 has shipped! Track: https://track.shop.com/abc123",
"sender_id": "ShopName",
"purpose": "order_notification",
"send_after": "2025-12-15T09:00:00Z",
"created_at": "2025-12-15T09:00:00Z",
"canceled_at": "2025-12-15T09:00:02Z"
}
}