Skip to the page

API basics

Versioning

The API is /v1 and webhook payloads carry a dated version that each webhook keeps. What BlueBot may add without warning, what counts as a breaking change, and how to move to a new version.

BlueBot versions its API in two places. Requests and answers are versioned by the path: everything in these docs is /v1. Webhook payloads are versioned by date: every event carries api_version, now 2026-11-13, and each webhook keeps the version it was made with. Code you write against either keeps working when BlueBot changes.

Where you see the version

WhereWhat it says
The pathhttps://usebluebot.com/api/v1/…
Every event, by webhook or from GET /v1/events"api_version": "2026-11-13": the shape of data.
Every webhook, from GET /v1/webhooks"api_version": "2026-11-13": the version it was made with and keeps.
GET /v1/status"api_version": the newest version.
The OpenAPI fileinfo.version: the version it describes.
curl "https://usebluebot.com/api/v1/status" \
  -H "Authorization: Bearer $BLUEBOT_API_KEY"
Response200BlueBot is up
{
  "object": "status",
  "status": "ok",
  "sending": "ok",
  "database": "ok",
  "api_version": "2026-11-13",
  "checked_at": "2026-11-13T19:41:00.000Z"
}

What BlueBot changes without a new version

These changes can come at any time, and your code should expect them:

  • New endpoints, and new optional fields and query parameters on existing ones.
  • New fields in answers and in event data. Read the fields you need and ignore the rest. The OpenAPI file never says an object’s fields are closed, so code generated from it accepts new ones.
  • New event types. A new type reaches a webhook made with ["*"] ("all_events": true) at once, and no webhook that lists its types until you add it to events with PATCH /v1/webhooks/{id}. Your handler should ignore types it doesn’t know. Webhooks
  • New values in a list of reasons, such as a new hold.reason, failure.reason or cancel_reason. Handle a value you don’t know the way you handle the closest general case, and log it.
  • New error codes for situations that had none before. Every error has a message and a hint you can show or log whatever its code.
  • Different words in message, hint, hold.description and failure.detail. Match on codes and reasons, never on words.
  • Different ids. An id’s prefix stays the same (msg_, chat_, ct_); the rest is opaque and may grow longer. Store ids as strings of any length.
  • Different limits and defaults that are your settings, such as the sending pace. The Limits page always has the current numbers.

What counts as a breaking change

BlueBot never makes these to /v1 or to a payload version once it’s out:

  • Removing or renaming a field, an endpoint, an event type or a value.
  • Changing a field’s type, or what it means.
  • Making an optional request field required, or refusing a request that used to be accepted.
  • Changing which error code a situation answers with.
  • Changing what an event’s data holds.

A change like that to requests or answers comes as /v2, beside /v1, so you choose when to move. A change like that to event payloads comes as a new api_version date. Webhooks made before it keep the old shape: BlueBot stores each event in the newest shape and changes it back for each webhook as it delivers it.

Before a version is retired, BlueBot emails the account owner at least 90 days ahead, and lists the change on the changelog. A version still in use is never turned off without that notice.

Moving a webhook to a new version

A webhook keeps its version for good; you can’t change it on an existing webhook. To move, make a new webhook beside the old one:

Make a new webhook

Make it with the same address and events, or a new address for a new handler. A new webhook gets the newest version.

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: move-crm-webhook-2026-11-13" \
  -d '{
    "url": "https://crm.example.com/bluebot/webhooks",
    "events": [
      "message.received",
      "message.failed"
    ],
    "description": "CRM, new payload version"
  }'

The answer carries the new webhook’s api_version and its own secret.

Handle both versions

For a while each event arrives twice, once from each webhook, and each signed with its own webhook’s secret. Read api_version on each event to tell the two shapes apart, and use the event id to handle each event once.

webhooks.ts
if (await alreadyHandled(event.id)) return;
if (event.api_version === '2026-11-13') {
    await handleCurrent(event);
} else {
    await handleOlder(event);
}

Delete the old webhook

Once your handler reads the new shape, delete the old webhook with DELETE /v1/webhooks/{id} or in the dashboard. From then on every event arrives once and in the new shape.

The SDKs and the OpenAPI file

The SDKs follow semantic versioning. A new minor version adds what BlueBot added; a new major version comes only with a breaking change in the SDK itself or a new API version, and its release notes say what to change.

The OpenAPI file describes /v1 as it is now, and its info.version names the newest payload version. Generating a client from it again after BlueBot adds something never breaks code written against an older copy.