Skip to the page

API reference

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.

POST/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. Keys and scopes

Send an Idempotency-Key so a retry never acts twice. Idempotency

Headers

  • Idempotency-Keystring

    Any 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

  • urlstringrequired

    An https address on the public internet. BlueBot doesn’t follow redirects.

    Up to 2,048 characters.

  • eventsarray of anyrequired

    The event types to send, or ["*"] for every type, including types BlueBot adds later.

  • descriptionstring

    Up to 200 characters.

Example

POST/v1/webhooksMake a webhook →
curl -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.

  • idstringrequired

    A wh_ id.

    Starts with wh_.

  • object"webhook"required
  • urlstringrequired
  • descriptionstring or nullrequired
  • eventsarray of stringsrequired

    The 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_eventsbooleanrequired

    True when it was made with ["*"]: it also receives event types BlueBot adds later.

  • api_versionstringrequired

    The payload version it was made with and keeps.

  • statusstringrequired

    active; failing while deliveries fail (retried for about 3 days); paused by you, or after 72 hours with no successful answer.

    One of active, failing, paused.

  • paused_attimestamp or nullrequired

    When it was paused.

  • pause_reasonstring or nullrequired

    Who paused it: failing (72 hours of failures), customer or staff.

    One of failing, customer, staff.

  • failing_sincetimestamp or nullrequired

    The first failure since the last success.

  • last_success_attimestamp or nullrequired

    The last delivery answered with a 2xx.

  • last_failure_attimestamp or nullrequired

    The last delivery that failed.

  • last_statusinteger or nullrequired

    The HTTP status of the last answer.

  • previous_secret_expires_attimestamp or nullrequired

    After a rotation, when the old secret stops signing alongside the new one.

  • created_attimestamprequired

    When it was made.

  • secretstringrequired

    The signing secret, whsec_ and base64. Verify webhook-signature with it. Shown when the webhook is made and when the secret is rotated.

Response201
{
  "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.

CodeStatusWhat it means
unauthorized401The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API.
insufficient_scope403The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope.
rate_limited429Too 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.
internal500Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe.
invalid_request400Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field.
limit_reached409The account has as many of something as it may have.
plan_lapsed402The 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.
idempotency_conflict409The Idempotency-Key was used in the last 24 hours with a different request. A key stands for one request.
conflict409The 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.