Make a webhook
BlueBot posts each event of the types you choose to url, signed the Standard Webhooks way with the secret in the answer, which is shown this once.
/v1/webhooks
BlueBot posts each event of the types you choose to url, signed the Standard Webhooks way with the secret in the answer, which is shown this once. A delivery that fails is tried again for about 3 days; after 72 hours with no 2xx the webhook is paused and you are emailed. Answering 410 deletes it.
Needs a key with the webhooks:manage scope.
Send an Idempotency-Key so a retry never acts twice.
Headers
Idempotency-KeystringAny string of up to 255 characters, new for each request. A retry with the same key gets the first answer back for 24 hours, with
Idempotent-Replayed: true.Up to 255 characters.
Request body
urlstringrequiredAn https address on the public internet. BlueBot doesn’t follow redirects.
Up to 2,048 characters.
eventsarray of anyrequiredThe event types to send, or
["*"]for every type, including types BlueBot adds later.descriptionstringUp to 200 characters.
Example
/v1/webhookscurl -X POST "https://usebluebot.com/api/v1/webhooks" \
-H "Authorization: Bearer $BLUEBOT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0f6d8c2e-5b1a-4c7e-9d3f-2a8b6e1c4d70" \
-d '{
"url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
"events": [
"message.received",
"message.failed"
],
"description": "New replies to my CRM"
}'Response
201: The webhook, with its signing secret.
idstringrequiredA wh_ id.
Starts with
wh_.object"webhook"requiredurlstringrequireddescriptionstring or nullrequiredeventsarray of stringsrequiredThe event types it receives. For a webhook made with
["*"], every type there is now.One of
message.queued,message.sent,message.delivered,message.read,message.failed,message.unconfirmed,message.expired,message.canceled,message.received,message.edited,message.unsent,reaction.added,reaction.removed,chat.created,contact.created,contact.stopped,contact.unstopped,sequence.completed,broadcast.completed,automation.matched,device.online,device.offline,device.check_failed.all_eventsbooleanrequiredTrue when it was made with
["*"]: it also receives event types BlueBot adds later.api_versionstringrequiredThe payload version it was made with and keeps.
statusstringrequiredactive;failingwhile deliveries fail (retried for about 3 days);pausedby you, or after 72 hours with no successful answer.One of
active,failing,paused.paused_attimestamp or nullrequiredWhen it was paused.
pause_reasonstring or nullrequiredWho paused it:
failing(72 hours of failures),customerorstaff.One of
failing,customer,staff.failing_sincetimestamp or nullrequiredThe first failure since the last success.
last_success_attimestamp or nullrequiredThe last delivery answered with a 2xx.
last_failure_attimestamp or nullrequiredThe last delivery that failed.
last_statusinteger or nullrequiredThe HTTP status of the last answer.
previous_secret_expires_attimestamp or nullrequiredAfter a rotation, when the old secret stops signing alongside the new one.
created_attimestamprequiredWhen it was made.
secretstringrequiredThe signing secret,
whsec_and base64. Verifywebhook-signaturewith it. Shown when the webhook is made and when the secret is rotated.
{
"id": "wh_1Hq2LxW9cVbN3mKpRtYs0a",
"object": "webhook",
"url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
"description": "New replies to my CRM",
"events": [
"message.received",
"message.failed"
],
"all_events": false,
"api_version": "2026-11-13",
"status": "active",
"paused_at": null,
"pause_reason": null,
"failing_since": null,
"last_success_at": null,
"last_failure_at": null,
"last_status": null,
"previous_secret_expires_at": null,
"created_at": "2026-11-01T15:10:00.000Z",
"secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}Errors
Every refusal has the same envelope and a page of its own. These are the ones this operation can give.
| Code | Status | What it means |
|---|---|---|
| 401 | The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API. | |
| 403 | The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope. | |
| 429 | Too many requests. A key may make 120 requests a minute. The RateLimit header says how many are left, and Retry-After how long to wait. | |
| 500 | Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe. | |
| 400 | Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field. | |
| 409 | The account has as many of something as it may have. | |
| 402 | The account’s plan isn’t active, so BlueBot isn’t taking new texts. Texts already queued wait and go once the plan is active again. | |
| 409 | The Idempotency-Key was used in the last 24 hours with a different request. A key stands for one request. | |
| 409 | The request doesn’t fit the thing’s current state, or another request with the same Idempotency-Key is still running. |
Try it
Call this operation from the page with your own key. The key stays in this tab and is forgotten when you leave.