Connect your systems to Inboxy — send every kind of WhatsApp message, create templates, campaigns and scheduled messages, and manage contacts, conversations, leads, tickets, orders, products and webhooks — with one API token.
The /public routes return this success shape; every other route returns its own JSON object. Every error on every route called with a token has the second shape, with any extra fields under details.
The body or query is invalid. The message says which field.
401
UNAUTHORIZED
Missing, revoked or expired token, or a route keys cannot call.
403
INSUFFICIENT_PERMISSIONS
The token lacks the scope this route needs.
403
SUBSCRIPTION_NOT_ACTIVE · FORBIDDEN
The plan or channel does not allow this action.
404
NOT_FOUND
The resource is not in your company.
409
CONFLICT
The resource is not in a state that allows this (for example a template missing its media).
429
TOO_MANY_REQUESTS
60 requests per minute per token.
500
INTERNAL_ERROR
Our fault. Retry later; quote the X-Request-Id header to support.
Webhooks
Register a public HTTPS URL and Inboxy calls it the moment something happens: messages on every channel, button taps, delivery and read receipts, tickets, leads, and every order change from connected stores.
Every request carries X-Inboxy-Timestamp and X-Inboxy-Signature = sha256=HMAC_SHA256(secret, "timestamp.body"). Get the secret from GET /webhooks/:id/secret.
import crypto from 'node:crypto';
// Use the raw request body — not a re-serialized object.
export function isFromInboxy(rawBody, headers, secret) {
const timestamp = headers['x-inboxy-timestamp'];
const received = headers['x-inboxy-signature'] || '';
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; // 5-minute window
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return received.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected));
}
Events (77)
message.*
message.received
When a new message is received
message.sent
When a message is sent
message.status_updated
When an outbound message is delivered, read or fails
contact.*
contact.created
When a new contact is created
contact.updated
When a contact is updated
conversation.*
conversation.opened
When a conversation is opened
conversation.closed
When a conversation is closed/resolved
conversation.assigned
When a conversation is assigned to an agent
conversation.created
A new conversation starts on any channel
conversation.resolved
A conversation is resolved or closed (by an agent, AI or automation)
order.*
order.created
When an order is created
order.updated
When an order status changes
order.completed
When an order is completed
order.cancelled
When an order is cancelled
campaign.*
campaign.started
When a campaign starts running
campaign.completed
When a campaign finishes
agent.*
agent.response
When an AI agent responds
whatsapp.*
whatsapp.message.received
WhatsApp: a text message arrives
whatsapp.media.received
WhatsApp: an image, video, audio, document or sticker arrives
whatsapp.voice.received
WhatsApp: a voice note arrives
whatsapp.location.received
WhatsApp: the customer shares a location
whatsapp.contact_card.received
WhatsApp: the customer shares a contact card
whatsapp.reaction.received
WhatsApp: the customer reacts to a message
whatsapp.button.clicked
WhatsApp: the customer taps a reply button
whatsapp.list.selected
WhatsApp: the customer picks a list row
whatsapp.template.reply
WhatsApp: the customer taps a template quick-reply button
whatsapp.flow.completed
WhatsApp: the customer submits a WhatsApp Flow
whatsapp.order.placed
WhatsApp: the customer sends a cart from the catalog
whatsapp.referral.received
WhatsApp: a conversation starts from a click-to-WhatsApp ad
whatsapp.message.status_changed
WhatsApp: an outbound message is sent, delivered, read or fails
instagram.*
instagram.message.received
Instagram: a DM arrives
instagram.media.received
Instagram: a DM with media arrives
instagram.reaction.received
Instagram: the customer reacts to a message
instagram.button.clicked
Instagram: the customer taps a button or quick reply
instagram.story.reply
Instagram: the customer replies to your story
instagram.story.mention
Instagram: the customer mentions you in their story
instagram.referral.received
Instagram: a conversation starts from an ad or link
instagram.first.inbound
Instagram: a customer's first message ever
messenger.*
messenger.message.received
Messenger: a message arrives
messenger.media.received
Messenger: a message with media arrives
messenger.voice.received
Messenger: a voice message arrives
messenger.location.received
Messenger: the customer shares a location
messenger.reaction.received
Messenger: the customer reacts to a message
messenger.button.clicked
Messenger: the customer taps a button or quick reply
messenger.template.reply
Messenger: the customer answers a template
messenger.referral.received
Messenger: a conversation starts from an ad or m.me link
messenger.first.inbound
Messenger: a customer's first message ever
telegram.*
telegram.message.received
Telegram: a message arrives
telegram.media.received
Telegram: a message with media arrives
telegram.location.received
Telegram: the customer shares a location
telegram.command.received
Telegram: the customer sends a /command
telegram.button.clicked
Telegram: the customer taps an inline button
telegram.first.inbound
Telegram: a customer's first message ever
widget.*
widget.chat.opened
Website chat: a visitor opens the chat
widget.message.received
Website chat: a visitor sends a message
widget.media.received
Website chat: a visitor sends a file
widget.button.clicked
Website chat: a visitor taps a button
widget.form.submitted
Website chat: a visitor submits a form
widget.first.inbound
Website chat: a visitor's first message ever
lead.*
lead.created
A lead is created
ticket.*
ticket.created
A support ticket is created
ticket.assigned
A ticket is assigned
ticket.status_changed
A ticket changes status
task.*
task.created
A task is created
task.assigned
A task is assigned
task.completed
A task is completed
web_event.*
web_event.received
Your website sends a tracked event (web events API)
curl -X GET "https://api.inboxy.chat/api/v1/whatsapp/templates" \
-H "Authorization: Bearer inboxy_your_token"
POST/api/v1/whatsapp/templatestemplates:write
Create a WhatsApp template and submit it to Meta for review
Requires templates:write permission.
Body
namerequired
string
Lowercase letters, digits and underscores. Unique per language.
categoryrequired
MARKETING | UTILITY | AUTHENTICATION
languagerequired
string
Meta language code.
templateType
STANDARD | CAROUSEL | LIMITED_TIME_OFFER
headerType
NONE | TEXT | IMAGE | VIDEO | DOCUMENT
headerText
string
TEXT headers: up to 60 characters, at most one {{1}}.
headerExample
string
TEXT headers: sample for {{1}}. IMAGE/VIDEO/DOCUMENT headers: the media handle from POST /api/v1/whatsapp/media/upload-for-template.
headerMediaUrl
string
Media headers: the public URL of the same file, stored so every send attaches it automatically.
bodyTextrequired
string
Up to 1,024 characters. Variables are {{1}}, {{2}}, … in order.
bodyExamples
string[]
One sample value per body variable, in order. Meta reviews the template with these.
footerText
string
Up to 60 characters, no variables.
buttons
object[]
Up to 10 buttons.
carouselCards
object[]
CAROUSEL templates: 2–10 cards, each with a media header, body and buttons.
ltoText
string
LIMITED_TIME_OFFER: the offer headline.
ltoExpiration
string
LIMITED_TIME_OFFER: when the offer ends.
ltoCouponCode
string
LIMITED_TIME_OFFER: coupon shown on a copy-code button.
authSecurityDisclaimer
boolean
AUTHENTICATION: add "Do not share this code" (default true).
authExpirationMinutes
number
AUTHENTICATION: code lifetime shown to the customer.
variableMapping
object
Required when bodyText has variables: one entry per variable number, saying where the value comes from at send time. Types: `static` (value used as-is), `contact_field` (firstName, lastName, name, email, phone), `custom_field` (a contact custom-field key), `order_field` (last.order.total, last.order.product, last.order.status, last.order.date, last.order.shipping_address, last.order.tracking_number), `web_event_field` (a path in the triggering web event).
curl -X GET "https://api.inboxy.chat/api/v1/whatsapp/campaigns" \
-H "Authorization: Bearer inboxy_your_token"
POST/api/v1/whatsapp/campaignscampaigns:write
Create a campaign
Requires campaigns:write permission.
Body
namerequired
string
templateIdrequired
string
An APPROVED template id (GET /api/v1/whatsapp/templates).
audiencerequired
object
Who receives the campaign. `ALL`: every opted-in contact. `TAGS`: contacts with any of `tagIds`. `CONTACTS`: exactly `contactIds` (max 5,000). `IMPORT_BATCH`: the `batchId` returned by import-audience.
templateComponents
object[]
Meta template components; omit to use the template’s saved variable mapping.
scheduledAt
string
Omit to create a draft; run it with POST /campaigns/:id/run.
curl -X GET "https://api.inboxy.chat/api/v1/whatsapp/campaigns/{id}" \
-H "Authorization: Bearer inboxy_your_token"
PUT/api/v1/whatsapp/campaigns/{id}campaigns:write
Update a draft or scheduled campaign
Requires campaigns:write permission.
Path parameters
idrequired
string
Body
name
string
templateId
string
audience
object
Who receives the campaign. `ALL`: every opted-in contact. `TAGS`: contacts with any of `tagIds`. `CONTACTS`: exactly `contactIds` (max 5,000). `IMPORT_BATCH`: the `batchId` returned by import-audience.
Who receives the campaign. `ALL`: every opted-in contact. `TAGS`: contacts with any of `tagIds`. `CONTACTS`: exactly `contactIds` (max 5,000). `IMPORT_BATCH`: the `batchId` returned by import-audience.
The event that starts the workflow — any webhook platform event name, e.g. "whatsapp.message.received", "ecommerce.cart.abandoned", "web_event.received".
Each node: `{ id, type, position?, label?, config?, version? }`. `type` is a registered node type (e.g. "whatsapp.send.text", "time.delay", "ticket.create"); `config` is validated per type on publish. Max 500. Easiest start: export a workflow built in the dashboard (GET …/:workflowId/export) and edit it.
edgesrequired
object[]
Each edge: `{ id, source, target, sourceHandle? }` referencing node ids. Max 1000.
The event that starts the workflow — any webhook platform event name, e.g. "whatsapp.message.received", "ecommerce.cart.abandoned", "web_event.received".
Each node: `{ id, type, position?, label?, config?, version? }`. `type` is a registered node type (e.g. "whatsapp.send.text", "time.delay", "ticket.create"); `config` is validated per type on publish. Max 500. Easiest start: export a workflow built in the dashboard (GET …/:workflowId/export) and edit it.
edgesrequired
object[]
Each edge: `{ id, source, target, sourceHandle? }` referencing node ids. Max 1000.
curl -X GET "https://api.inboxy.chat/api/v1/ecommerce/customers" \
-H "Authorization: Bearer inboxy_your_token"
GET/api/v1/ecommerce/customers/{id}ecommerce:read
Get a store customer with orders
Requires ecommerce:read permission.
Path parameters
idrequired
string
curl -X GET "https://api.inboxy.chat/api/v1/ecommerce/customers/{id}" \
-H "Authorization: Bearer inboxy_your_token"
Webhooks
GET/api/v1/webhooks/eventswebhooks:read
List webhook event types
Requires webhooks:read permission.
curl -X GET "https://api.inboxy.chat/api/v1/webhooks/events" \
-H "Authorization: Bearer inboxy_your_token"
GET/api/v1/webhookswebhooks:read
List webhooks
Requires webhooks:read permission.
curl -X GET "https://api.inboxy.chat/api/v1/webhooks" \
-H "Authorization: Bearer inboxy_your_token"
POST/api/v1/webhookswebhooks:write
Register a webhook
Requires webhooks:write permission.
Body
namerequired
string
Webhook name.
urlrequired
string
HTTPS endpoint to receive events. Must be a public, non-private-network URL.
eventsrequired
string[]
Events to receive: exact names from GET /api/v1/webhooks/events, "*" for everything, or a prefix wildcard such as "whatsapp.*", "ecommerce.order.*" or "ticket.*".
maxRetries
number
Max delivery retry attempts.
fieldExclusions
string[]
Dot-separated payload paths to omit from delivered payloads (max 20).
consecutiveFailureThreshold
number
Consecutive failures (5-1000) before the webhook auto-pauses.
curl -X GET "https://api.inboxy.chat/api/v1/webhooks/{webhookId}" \
-H "Authorization: Bearer inboxy_your_token"
PUT/api/v1/webhooks/{webhookId}webhooks:write
Update a webhook
Requires webhooks:write permission.
Path parameters
webhookIdrequired
string
Body
name
string
Webhook name.
url
string
HTTPS endpoint to receive events.
events
string[]
Events to receive: exact names from GET /api/v1/webhooks/events, "*" for everything, or a prefix wildcard such as "whatsapp.*", "ecommerce.order.*" or "ticket.*".
status
ACTIVE | PAUSED | FAILED
Webhook status.
maxRetries
number
Max delivery retry attempts.
fieldExclusions
string[]
Dot-separated payload paths to omit from delivered payloads (max 20).
consecutiveFailureThreshold
number
Consecutive failures (5-1000) before the webhook auto-pauses.
Get a paginated list of products from the catalog. Requires products:read permission.
Query parameters
page
integer
pageSize
integer
search
string
Search by product name or SKU
categoryId
string
Filter by category ID
isActive
boolean
Filter by active status
curl -X GET "https://api.inboxy.chat/api/v1/public/products" \
-H "Authorization: Bearer inboxy_your_token"
GET/api/v1/public/products/{id}products:read
Get product by ID
Get a single product with full details. Requires products:read permission.
Path parameters
idrequired
string
Resource ID
curl -X GET "https://api.inboxy.chat/api/v1/public/products/{id}" \
-H "Authorization: Bearer inboxy_your_token"
Web events
GET/api/v1/web-eventsautomations:read
List web event integrations
Requires automations:read permission.
curl -X GET "https://api.inboxy.chat/api/v1/web-events" \
-H "Authorization: Bearer inboxy_your_token"
POST/api/v1/web-eventsautomations:write
Create an integration your website posts events to
Requires automations:write permission.
Body
namerequired
string
description
string
authTyperequired
HMAC_SHA256 | API_KEY
How your site authenticates when it posts events to POST /api/webhook/web-events/:integrationId — an `X-Webhook-Signature` HMAC-SHA256 of the raw body, or the secret in `X-Api-Key`. The secret is shown in the dashboard.
autoCreateContact
boolean
Create a contact when an event matches none.
contactMapping
object
`{ phoneField, emailField, nameField?, autoCreate, enrichFields?, displayColumns? }` — which JSON fields identify the contact.
curl -X GET "https://api.inboxy.chat/api/v1/web-events/{id}" \
-H "Authorization: Bearer inboxy_your_token"
PUT/api/v1/web-events/{id}automations:write
Update an integration
Requires automations:write permission.
Path parameters
idrequired
string
Body
namerequired
string
description
string
authTyperequired
HMAC_SHA256 | API_KEY
How your site authenticates when it posts events to POST /api/webhook/web-events/:integrationId — an `X-Webhook-Signature` HMAC-SHA256 of the raw body, or the secret in `X-Api-Key`. The secret is shown in the dashboard.
autoCreateContact
boolean
Create a contact when an event matches none.
contactMapping
object
`{ phoneField, emailField, nameField?, autoCreate, enrichFields?, displayColumns? }` — which JSON fields identify the contact.
Connection status of every channel (WhatsApp, Instagram, Messenger, Telegram, website chat)
Aggregate connection state for all channels (WhatsApp, Instagram, Messenger, Telegram, Widget). One request, parallel-fetched. Requires channels:read permission.
curl -X GET "https://api.inboxy.chat/api/v1/me/channels" \
-H "Authorization: Bearer inboxy_your_token"
curl -X GET "https://api.inboxy.chat/api/v1/scheduled-messages" \
-H "Authorization: Bearer inboxy_your_token"
POST/api/v1/scheduled-messagesmessages:send
Schedule a message
Requires messages:send permission.
Body
channelrequired
WHATSAPP | INSTAGRAM | MESSENGER | TELEGRAM | SMS
recipientRefrequired
string
Phone number (WhatsApp/SMS) or the channel’s recipient id.
scheduledForrequired
string
conversationId
string
recurrence
NONE | DAILY | WEEKLY | MONTHLY
payloadrequired
object
`{kind:"text", text}` or `{kind:"template", templateName, languageCode, bodyVariables?, components?}`. Outside the 24-hour window WhatsApp needs a template; the response says `window_requires_template`.