{
  "openapi": "3.1.0",
  "info": {
    "title": "BlueBot API",
    "version": "2026-11-13",
    "description": "BlueBot sends texts from your own number through your own Mac, and tells you about every text in and out.\n\n**Keys.** Send `Authorization: Bearer bb_live_…`. Make keys on the API keys page; each has scopes, and each operation names the scope it needs.\n\n**Holds.** A text that can’t go now is accepted and held, never refused: its `hold` says why (quiet hours, the Mac offline, a daily limit, pacing) and until when.\n\n**Idempotency.** Send an `Idempotency-Key` on every POST. The first answer is kept 24 hours and returned for a retry with the same key; the same key with a different request is refused with `idempotency_conflict`.\n\n**Rate limits.** 120 requests a minute per key. Every answer carries `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`; a 429 carries `Retry-After`.\n\n**Errors.** Every refusal is `{ \"error\": { code, message, hint, doc_url, request_id } }`. Each code has a page at `doc_url`.\n\n**Lists** are newest first. Pass the answer’s `next_cursor` as `cursor` for the next page.\n\n**Versions.** The API is `/v1`. Webhook payloads carry `api_version` (now `2026-11-13`), and each webhook keeps the version it was made with.",
    "contact": {
      "name": "BlueBot support",
      "email": "support@usebluebot.com"
    }
  },
  "servers": [
    {
      "url": "https://usebluebot.com/api/v1",
      "description": "BlueBot"
    },
    {
      "url": "http://localhost:3100/api/v1",
      "description": "Local development"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "Messages",
      "description": "Send texts, read them, schedule them and cancel them."
    },
    {
      "name": "Files",
      "description": "Pictures, video, voice memos and other files to send, and the ones that arrive."
    },
    {
      "name": "Chats",
      "description": "Group chats and one-to-one chats the Mac has seen."
    },
    {
      "name": "Lookup",
      "description": "Whether a number is on iMessage, from your own history."
    },
    {
      "name": "Device",
      "description": "Your Mac and BlueBot’s own status."
    },
    {
      "name": "Settings",
      "description": "The sending rules."
    },
    {
      "name": "Stops",
      "description": "People who asked not to be texted."
    },
    {
      "name": "Events",
      "description": "The last 30 days of events."
    },
    {
      "name": "Webhooks",
      "description": "Addresses BlueBot posts events to."
    },
    {
      "name": "Account",
      "description": "Who a key belongs to."
    },
    {
      "name": "Conversations",
      "description": "Your texts grouped by person or group chat, as the inbox shows them."
    },
    {
      "name": "Analytics",
      "description": "Texting numbers and the conversations waiting on you."
    },
    {
      "name": "Contacts",
      "description": "The people you text, their tags and custom fields."
    },
    {
      "name": "Templates",
      "description": "Saved texts with variables."
    },
    {
      "name": "Broadcasts",
      "description": "One text to a list of people who asked to hear from you, paced by your Mac."
    },
    {
      "name": "Sequences",
      "description": "Texts with waits between them that stop when the person replies."
    },
    {
      "name": "Text Hooks",
      "description": "Addresses that turn any app’s webhook post into a text."
    },
    {
      "name": "Automations",
      "description": "Keyword auto-replies and the away message."
    }
  ],
  "paths": {
    "/messages": {
      "post": {
        "operationId": "sendMessage",
        "summary": "Send a text",
        "description": "Queues a text from your own number. The answer is the message, usually `queued`; a text that can’t go right now is accepted and carries a `hold` saying why (quiet hours, the Mac offline, a daily limit, its turn in the pacing) and goes on its own once the hold ends, unless it expires first.\n\nSend `to` for one person or `chat_id` for an existing group chat. `send_at` schedules it; a scheduled text can be changed with `PATCH /v1/messages/{id}` until it is due. A text to somebody on your stop list is accepted and canceled at once with `cancel_reason: \"opted_out\"`.\n\nSend `text` for your own words, or `template_id` with `variables` to send a saved template. A template is filled from `variables`, then from the person’s contact and your business name; a variable left with no value and no fallback refuses the send with `invalid_request`, naming it under `details`, and a template that isn’t yours answers `not_found`. The text records the template’s id as its `source_ref`.\n\nSend an `Idempotency-Key` so a retry never sends twice: the first answer is kept 24 hours.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "plan_lapsed",
          "idempotency_conflict",
          "conflict",
          "payload_too_large",
          "unsupported_media_type"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "description": "Who to text. Send `to` or `chat_id`, not both.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320,
                    "examples": [
                      "+15555550123"
                    ]
                  },
                  "chat_id": {
                    "description": "An existing group chat to text into, from `GET /v1/chats`. Send `to` or `chat_id`, not both.",
                    "type": "string",
                    "pattern": "^chat_[0-9A-Za-z]{22}$",
                    "examples": [
                      "chat_1Hq2LxW9cVbN3mKpRtYs0a"
                    ]
                  },
                  "text": {
                    "description": "The words, up to 2000 characters. Send `text` or `template_id`, not both; may be left out when `files` has something.",
                    "examples": [
                      "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM."
                    ],
                    "type": "string",
                    "maxLength": 2000
                  },
                  "template_id": {
                    "description": "Send a saved template instead of `text`. Its `{{variables}}` are filled from `variables`, then from the person’s contact (`first_name`, `last_name`, `company`, custom fields) and your business name (`business`). A variable with no value and no fallback refuses the send, naming it.",
                    "type": "string",
                    "pattern": "^tpl_[0-9A-Za-z]{22}$",
                    "examples": [
                      "tpl_1Hq2LxW9cVbN3mKpRtYs0a"
                    ]
                  },
                  "variables": {
                    "description": "Values for the template’s `{{variables}}`, by name. They win over the contact’s own fields. Only with `template_id`.",
                    "examples": [
                      {
                        "time": "3 PM",
                        "address": "412 Oak St"
                      }
                    ],
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    }
                  },
                  "files": {
                    "description": "Up to 10 files from `POST /v1/files`, sent after the words in this order.",
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^file_[0-9A-Za-z]{22}$",
                      "description": "A file_ id.",
                      "examples": [
                        "file_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    }
                  },
                  "service": {
                    "default": "auto",
                    "description": "`auto` (the default) uses whatever the newest chat with the person used, else iMessage, and sends an iMessage that never went once more as a regular text. `imessage` never falls back; `sms` sends a regular text through your iPhone.",
                    "type": "string",
                    "enum": [
                      "auto",
                      "imessage",
                      "sms"
                    ]
                  },
                  "send_at": {
                    "description": "Schedule it. A scheduled text is a draft you can change with `PATCH /v1/messages/{id}` until it is due.",
                    "type": "string",
                    "format": "date-time"
                  },
                  "expires_at": {
                    "description": "Give up on it if it is still waiting at this time. Default: 24 hours after it is due (a setting).",
                    "type": "string",
                    "format": "date-time"
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own data, echoed on the message and on every webhook about it: up to 20 keys of up to 40 characters, each a string of up to 500.",
                    "examples": [
                      {
                        "zap": "new-lead",
                        "crm_id": "48213"
                      }
                    ]
                  }
                },
                "description": "A text to send."
              },
              "example": {
                "to": "+15555550123",
                "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                "metadata": {
                  "crm_id": "48213"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The text, accepted.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "queued",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`: Payload too large.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "payload_too_large": {
                    "summary": "Payload too large",
                    "value": {
                      "error": {
                        "code": "payload_too_large",
                        "message": "Files can be up to 25 MB.",
                        "hint": "Send less. The docs list each size limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/payload_too_large",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: Unsupported media type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_media_type": {
                    "summary": "Unsupported media type",
                    "value": {
                      "error": {
                        "code": "unsupported_media_type",
                        "message": "Send `Content-Type: application/json`.",
                        "hint": "Send `Content-Type: application/json`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unsupported_media_type",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listMessages",
        "summary": "List texts",
        "description": "Texts in and out, newest first, including ones typed by hand on your Mac or iPhone (`source: \"mac\"`). Filter by person, chat, state, direction, source or time.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "description": "Only texts out, or only texts in.",
            "schema": {
              "type": "string",
              "enum": [
                "out",
                "in"
              ]
            }
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Only texts in this state.",
            "schema": {
              "type": "string",
              "enum": [
                "scheduled",
                "queued",
                "sending",
                "sent",
                "delivered",
                "read",
                "failed",
                "unconfirmed",
                "expired",
                "canceled",
                "received"
              ]
            }
          },
          {
            "name": "person",
            "in": "query",
            "required": false,
            "description": "Only texts with this person (a phone number or an email address).",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320,
              "examples": [
                "+15555550123"
              ]
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only texts with this contact.",
            "schema": {
              "type": "string",
              "pattern": "^ct_[0-9A-Za-z]{22}$",
              "examples": [
                "ct_1Hq2LxW9cVbN3mKpRtYs0a"
              ]
            }
          },
          {
            "name": "chat_id",
            "in": "query",
            "required": false,
            "description": "Only texts in this group chat.",
            "schema": {
              "type": "string",
              "pattern": "^chat_[0-9A-Za-z]{22}$",
              "examples": [
                "chat_1Hq2LxW9cVbN3mKpRtYs0a"
              ]
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Only texts from this source.",
            "schema": {
              "type": "string",
              "enum": [
                "api",
                "zapier",
                "make",
                "n8n",
                "pipedream",
                "cli",
                "mcp",
                "hook",
                "broadcast",
                "sequence",
                "inbox",
                "autopilot",
                "keyword",
                "away",
                "widget",
                "assistant",
                "test",
                "mac"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only texts created at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "description": "Only texts created before this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of texts.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "message",
                      "direction": "out",
                      "state": "sent",
                      "to": "+15555550123",
                      "from": "+15555550100",
                      "chat_id": null,
                      "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                      "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                      "text_deleted": false,
                      "files": [],
                      "service_requested": "auto",
                      "service": "imessage",
                      "sms_retry": false,
                      "source": "api",
                      "source_ref": null,
                      "metadata": {
                        "crm_id": "48213"
                      },
                      "hold": null,
                      "send_at": null,
                      "expires_at": "2026-11-14T19:41:00.000Z",
                      "failure": null,
                      "cancel_reason": null,
                      "resolution": null,
                      "resolved_at": null,
                      "resent_message_id": null,
                      "reply_to_id": null,
                      "reactions": [],
                      "edited_at": null,
                      "unsent_at": null,
                      "created_at": "2026-11-13T19:41:00.000Z",
                      "queued_at": "2026-11-13T19:41:00.000Z",
                      "sending_at": "2026-11-13T19:41:02.000Z",
                      "sent_at": "2026-11-13T19:41:05.000Z",
                      "delivered_at": null,
                      "read_at": null,
                      "failed_at": null,
                      "unconfirmed_at": null,
                      "expired_at": null,
                      "canceled_at": null,
                      "received_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}": {
      "get": {
        "operationId": "getMessage",
        "summary": "Get a text",
        "description": "One text, with its state, hold, files and tapbacks.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The text’s id.",
            "schema": {
              "type": "string",
              "pattern": "^msg_[0-9A-Za-z]{22}$"
            },
            "example": "msg_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The text.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "sent",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": "2026-11-13T19:41:05.000Z",
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateMessage",
        "summary": "Change a scheduled text",
        "description": "Changes the words, time, expiry or metadata of a text that is still `scheduled`. Once it is due it can only be canceled.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "conflict",
          "plan_lapsed"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The text’s id.",
            "schema": {
              "type": "string",
              "pattern": "^msg_[0-9A-Za-z]{22}$"
            },
            "example": "msg_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "description": "New words. Null removes them, which needs files on the text.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "send_at": {
                    "description": "A new time to send it.",
                    "type": "string",
                    "format": "date-time"
                  },
                  "expires_at": {
                    "description": "A new expiry; null for the default.",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "description": "Replaces the metadata.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "examples": [
                      {
                        "zap": "new-lead",
                        "crm_id": "48213"
                      }
                    ]
                  }
                },
                "description": "Changes to a scheduled text."
              },
              "example": {
                "send_at": "2026-11-14T15:00:00.000Z"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed text.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "scheduled",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": "2026-11-14T15:00:00.000Z",
                  "expires_at": "2026-11-15T15:00:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": null,
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}/cancel": {
      "post": {
        "operationId": "cancelMessage",
        "summary": "Cancel a text",
        "description": "Cancels a text that is `scheduled` or `queued`. A text the Mac already took can’t be called back.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The text’s id.",
            "schema": {
              "type": "string",
              "pattern": "^msg_[0-9A-Za-z]{22}$"
            },
            "example": "msg_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The canceled text.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "canceled",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": "requested",
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": "2026-11-13T19:42:00.000Z",
                  "received_at": null
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/messages/{id}/resolve": {
      "post": {
        "operationId": "resolveMessage",
        "summary": "Settle an unconfirmed text",
        "description": "An `unconfirmed` text is one the Mac took and couldn’t confirm before its lease ran out; it may have gone. Look at the conversation, then `mark_sent` if the person got it or `send_again` to queue a new text with the same words, files and metadata. BlueBot never sends one again on its own.",
        "tags": [
          "Messages"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "conflict",
          "plan_lapsed"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The text’s id.",
            "schema": {
              "type": "string",
              "pattern": "^msg_[0-9A-Za-z]{22}$"
            },
            "example": "msg_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "mark_sent",
                      "send_again"
                    ],
                    "description": "`mark_sent` when the person got it; `send_again` queues a new text with the same words, files and metadata."
                  }
                },
                "required": [
                  "action"
                ],
                "description": "How to settle an unconfirmed text."
              },
              "example": {
                "action": "send_again"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The settled text. For `send_again`, `resent_message_id` names the new one.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "example": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "unconfirmed",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": "resent",
                  "resolved_at": "2026-11-13T19:50:00.000Z",
                  "resent_message_id": "msg_3Lp3VsC7hGqE5tZyKbWn2d",
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": "2026-11-13T19:44:02.000Z",
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files": {
      "post": {
        "operationId": "uploadFile",
        "summary": "Upload a file",
        "description": "Uploads a picture, video, audio file, PDF or contact card (.vcf) of up to 25 MB to send. Send the answer’s `id` in `files` on a send. A file nobody sends is deleted after a day.",
        "tags": [
          "Files"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "payload_too_large",
          "unsupported_media_type",
          "plan_lapsed",
          "idempotency_conflict",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "The file, up to 25 MB: a picture, video, audio, a PDF or a contact card (.vcf)."
                  },
                  "name": {
                    "description": "A name to send it under, if not the file’s own.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The file.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                },
                "example": {
                  "id": "file_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "file",
                  "name": "listing-412-oak.jpg",
                  "content_type": "image/jpeg",
                  "size": 482113,
                  "kind": "image",
                  "status": "ready",
                  "url": "https://usebluebot.com/files/f/2Bf8QzD4kJmA6nXwEuTr1c?sig=…",
                  "url_expires_at": "2026-11-13T20:41:00.000Z",
                  "transcript": null,
                  "transcript_language": null,
                  "created_at": "2026-11-13T19:40:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`: Payload too large.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "payload_too_large": {
                    "summary": "Payload too large",
                    "value": {
                      "error": {
                        "code": "payload_too_large",
                        "message": "Files can be up to 25 MB.",
                        "hint": "Send less. The docs list each size limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/payload_too_large",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: Unsupported media type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unsupported_media_type": {
                    "summary": "Unsupported media type",
                    "value": {
                      "error": {
                        "code": "unsupported_media_type",
                        "message": "Send `Content-Type: application/json`.",
                        "hint": "Send `Content-Type: application/json`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unsupported_media_type",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/files/{id}": {
      "get": {
        "operationId": "getFile",
        "summary": "Get a file",
        "description": "A file, with a fresh `url` that reads it for an hour.",
        "tags": [
          "Files"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The file’s id.",
            "schema": {
              "type": "string",
              "pattern": "^file_[0-9A-Za-z]{22}$"
            },
            "example": "file_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The file.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                },
                "example": {
                  "id": "file_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "file",
                  "name": "listing-412-oak.jpg",
                  "content_type": "image/jpeg",
                  "size": 482113,
                  "kind": "image",
                  "status": "ready",
                  "url": "https://usebluebot.com/files/f/2Bf8QzD4kJmA6nXwEuTr1c?sig=…",
                  "url_expires_at": "2026-11-13T20:41:00.000Z",
                  "transcript": null,
                  "transcript_language": null,
                  "created_at": "2026-11-13T19:40:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/chats": {
      "get": {
        "operationId": "listChats",
        "summary": "List chats",
        "description": "The chats the Mac has seen, newest first, with their participants. A group chat’s `id` is what `chat_id` takes on a send.",
        "tags": [
          "Chats"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "is_group",
            "in": "query",
            "required": false,
            "description": "`true` for only group chats, `false` for only one-to-one chats.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "person",
            "in": "query",
            "required": false,
            "description": "Only chats this person is in.",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320,
              "examples": [
                "+15555550123"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of chats.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Chat"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "chat",
                      "name": "Oak St closing",
                      "is_group": true,
                      "participants": [
                        "+15555550123",
                        "+15555550187"
                      ],
                      "service": "imessage",
                      "last_message_at": "2026-11-13T19:41:00.000Z",
                      "created_at": "2026-11-02T14:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/chats/{id}": {
      "get": {
        "operationId": "getChat",
        "summary": "Get a chat",
        "description": "One chat and its participants.",
        "tags": [
          "Chats"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The chat’s id.",
            "schema": {
              "type": "string",
              "pattern": "^chat_[0-9A-Za-z]{22}$"
            },
            "example": "chat_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The chat.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Chat"
                },
                "example": {
                  "id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "chat",
                  "name": "Oak St closing",
                  "is_group": true,
                  "participants": [
                    "+15555550123",
                    "+15555550187"
                  ],
                  "service": "imessage",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_at": "2026-11-02T14:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/lookup": {
      "get": {
        "operationId": "lookupNumber",
        "summary": "Is this number on iMessage?",
        "description": "A best guess from your own Messages history: what the newest chat with the person used. BlueBot asks the Mac and waits up to 15 seconds; `basis` says what the answer rests on. Apple offers no way to ask about a number you have never texted, so that answer is `unknown`.",
        "tags": [
          "Lookup"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "number",
            "in": "query",
            "required": true,
            "description": "The phone number or email address to look up.",
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320,
              "examples": [
                "+15555550123"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The answer and its basis.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lookup"
                },
                "example": {
                  "object": "lookup",
                  "handle": "+15555550123",
                  "service": "imessage",
                  "basis": "history",
                  "last_seen_at": "2026-11-12T16:20:00.000Z",
                  "checked_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/device": {
      "get": {
        "operationId": "getDevice",
        "summary": "Get the Mac",
        "description": "The Mac that sends for you: whether it is online, its setup checks, how many texts are waiting and today’s counts against the limits.",
        "tags": [
          "Device"
        ],
        "x-scope": "account:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "The Mac.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                },
                "example": {
                  "id": "dev_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "device",
                  "status": "online",
                  "name": "Dana’s MacBook Air",
                  "number": "+15555550100",
                  "app_version": "1.0.0",
                  "macos_version": "15.1",
                  "last_seen_at": "2026-11-13T19:41:00.000Z",
                  "last_sync_at": "2026-11-13T19:41:00.000Z",
                  "offline_since": null,
                  "paired_at": "2026-11-01T15:00:00.000Z",
                  "checks": {
                    "messages": {
                      "state": "ok",
                      "detail": null
                    },
                    "full_disk_access": {
                      "state": "ok",
                      "detail": null
                    },
                    "forwarding": {
                      "state": "ok",
                      "detail": null
                    },
                    "awake": {
                      "state": "ok",
                      "detail": null
                    },
                    "filevault": {
                      "state": "ok",
                      "detail": null
                    }
                  },
                  "checks_ok": true,
                  "transcription": false,
                  "held_count": 0,
                  "queued_count": 0,
                  "unconfirmed_count": 0,
                  "paused_until": null,
                  "today": {
                    "sent": 14,
                    "new_people": 3,
                    "new_people_limit": 50,
                    "daily_limit": 1000,
                    "resets_at": "2026-11-14T05:00:00.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "BlueBot’s status",
        "description": "Whether BlueBot itself is up. Needs no key. For your own Mac, see `GET /v1/device`.",
        "tags": [
          "Device"
        ],
        "security": [],
        "x-error-codes": [
          "rate_limited",
          "internal",
          "unavailable"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "BlueBot’s status.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Status"
                },
                "example": {
                  "object": "status",
                  "status": "ok",
                  "sending": "ok",
                  "database": "ok",
                  "api_version": "2026-11-13",
                  "checked_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "`unavailable`: Unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unavailable": {
                    "summary": "Unavailable",
                    "value": {
                      "error": {
                        "code": "unavailable",
                        "message": "BlueBot isn’t taking requests right now.",
                        "hint": "BlueBot is not taking requests right now. Try again shortly.",
                        "doc_url": "https://usebluebot.com/docs/errors/unavailable",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Who am I?",
        "description": "The account and key a request acts as, the plan and whether the Mac is online. A quick way to check a key works.",
        "tags": [
          "Account"
        ],
        "x-scope": "account:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "The account and key.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                },
                "example": {
                  "object": "me",
                  "account": {
                    "id": "acct_1Hq2LxW9cVbN3mKpRtYs0a",
                    "email": "dana@example.com",
                    "name": "Dana Reyes",
                    "time_zone": "America/Chicago",
                    "created_at": "2026-11-01T15:00:00.000Z"
                  },
                  "key": {
                    "id": "key_1Hq2LxW9cVbN3mKpRtYs0a",
                    "name": "Zapier",
                    "prefix": "bb_live_7Hq2Lx",
                    "mode": "live",
                    "scopes": [
                      "messages:send",
                      "messages:read",
                      "contacts:write",
                      "contacts:read",
                      "webhooks:manage",
                      "account:read"
                    ],
                    "created_at": "2026-11-01T15:10:00.000Z"
                  },
                  "plan": {
                    "status": "active",
                    "active": true,
                    "trial_end": null,
                    "current_period_end": "2026-12-01T15:00:00.000Z"
                  },
                  "device": {
                    "status": "online"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/settings": {
      "get": {
        "operationId": "getSettings",
        "summary": "Get the sending rules",
        "description": "Pacing, new people per day, quiet hours, stop words, expiry and which chats the Mac copies.",
        "tags": [
          "Settings"
        ],
        "x-scope": "account:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "The settings.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Settings"
                },
                "example": {
                  "object": "settings",
                  "business_name": "Dana Realty",
                  "time_zone": "America/Chicago",
                  "pace_seconds": 20,
                  "new_people_per_day": 50,
                  "quiet_hours": {
                    "enabled": true,
                    "start": "21:00",
                    "end": "08:00"
                  },
                  "smart_quiet_hours": false,
                  "stop_words": {
                    "enabled": true,
                    "words": [
                      "stop",
                      "stopall",
                      "unsubscribe",
                      "cancel",
                      "end",
                      "quit"
                    ],
                    "custom": false,
                    "start_words": [
                      "start",
                      "unstop",
                      "yes"
                    ]
                  },
                  "expiry_hours": 24,
                  "inbound_mode": "replies",
                  "paused_until": null,
                  "platform_daily_limit": 1000,
                  "warnings": []
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateSettings",
        "summary": "Change the sending rules",
        "description": "Changes the settings you send; the rest stay. Texts already waiting are held, or freed, under the new rules within a minute. `paused_until` pauses all sending until a time, and null resumes it. `stop_words.words` replaces the stop words with your own list; null goes back to the defaults.",
        "tags": [
          "Settings"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "business_name": {
                    "description": "Your business’s name, as `{{business}}` fills it in. Null clears it.",
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 120
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "time_zone": {
                    "description": "An IANA zone, such as `America/Chicago`.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "pace_seconds": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 300
                  },
                  "new_people_per_day": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 1000
                  },
                  "quiet_hours": {
                    "type": "object",
                    "properties": {
                      "enabled": {
                        "type": "boolean"
                      },
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                      }
                    }
                  },
                  "smart_quiet_hours": {
                    "type": "boolean"
                  },
                  "stop_words": {
                    "type": "object",
                    "properties": {
                      "enabled": {
                        "type": "boolean"
                      },
                      "words": {
                        "description": "Your own stop words, matched without case against a whole reply. Null goes back to the defaults.",
                        "anyOf": [
                          {
                            "minItems": 1,
                            "maxItems": 50,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 30,
                              "pattern": "^[\\p{L}\\p{N}' ]+$"
                            }
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    }
                  },
                  "expiry_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 168
                  },
                  "inbound_mode": {
                    "type": "string",
                    "enum": [
                      "replies",
                      "everything"
                    ]
                  },
                  "paused_until": {
                    "description": "Pause sending until this time; null resumes.",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "description": "The settings to change. Leave out what stays the same."
              },
              "example": {
                "pace_seconds": 30,
                "quiet_hours": {
                  "start": "20:00"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The settings after the change.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Settings"
                },
                "example": {
                  "object": "settings",
                  "business_name": "Dana Realty",
                  "time_zone": "America/Chicago",
                  "pace_seconds": 30,
                  "new_people_per_day": 50,
                  "quiet_hours": {
                    "enabled": true,
                    "start": "20:00",
                    "end": "08:00"
                  },
                  "smart_quiet_hours": false,
                  "stop_words": {
                    "enabled": true,
                    "words": [
                      "stop",
                      "stopall",
                      "unsubscribe",
                      "cancel",
                      "end",
                      "quit"
                    ],
                    "custom": false,
                    "start_words": [
                      "start",
                      "unstop",
                      "yes"
                    ]
                  },
                  "expiry_hours": 24,
                  "inbound_mode": "replies",
                  "paused_until": null,
                  "platform_daily_limit": 1000,
                  "warnings": []
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stops": {
      "get": {
        "operationId": "listStops",
        "summary": "List the stop list",
        "description": "People BlueBot won’t text, newest first: those who texted a stop word and those you added.",
        "tags": [
          "Stops"
        ],
        "x-scope": "contacts:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of stops.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Stop"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "stop",
                      "handle": "+15555550144",
                      "contact_id": "ct_4Mr6NdF1jHwS8aPxQcUv3e",
                      "stopped_at": "2026-11-10T22:05:00.000Z",
                      "source": "reply"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "addStop",
        "summary": "Stop texting somebody",
        "description": "Puts a person on the stop list and cancels their queued and scheduled texts. Adding somebody already on it changes nothing.",
        "tags": [
          "Stops"
        ],
        "x-scope": "contacts:write",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "idempotency_conflict",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "person": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320,
                    "description": "The phone number or email address to stop texting.",
                    "examples": [
                      "+15555550123"
                    ]
                  }
                },
                "required": [
                  "person"
                ]
              },
              "example": {
                "person": "+15555550144"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The stop.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Stop"
                },
                "example": {
                  "object": "stop",
                  "handle": "+15555550144",
                  "contact_id": "ct_4Mr6NdF1jHwS8aPxQcUv3e",
                  "stopped_at": "2026-11-13T19:41:00.000Z",
                  "source": "api"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/stops/{person}": {
      "delete": {
        "operationId": "removeStop",
        "summary": "Text somebody again",
        "description": "Takes a person off the stop list. Texts canceled while they were on it stay canceled. Only take somebody off who asked to be texted again.",
        "tags": [
          "Stops"
        ],
        "x-scope": "contacts:write",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "person",
            "in": "path",
            "required": true,
            "description": "The phone number or email address, URL-encoded (`%2B15555550144`).",
            "schema": {
              "type": "string"
            },
            "example": "%2B15555550144"
          }
        ],
        "responses": {
          "200": {
            "description": "The stop is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "stop"
                    },
                    "handle": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "object",
                    "handle",
                    "deleted"
                  ]
                },
                "example": {
                  "object": "stop",
                  "handle": "+15555550144",
                  "deleted": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/events": {
      "get": {
        "operationId": "listEvents",
        "summary": "List events",
        "description": "The last 30 days of events, newest first, in the shape a webhook receives them. Use it to catch up after missing deliveries.",
        "tags": [
          "Events"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Only these types, comma-separated, such as `message.received,message.failed`.",
            "schema": {
              "examples": [
                "message.received"
              ],
              "type": "string"
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only events at or after this time. Events are kept 30 days.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "event",
                      "type": "message.received",
                      "api_version": "2026-11-13",
                      "timestamp": "2026-11-13T19:41:00.000Z",
                      "data": {
                        "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                        "object": "message",
                        "direction": "in",
                        "state": "received",
                        "to": "+15555550100",
                        "from": "+15555550123",
                        "chat_id": null,
                        "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                        "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                        "text": "Perfect, see you there!",
                        "text_deleted": false,
                        "files": [],
                        "service_requested": "auto",
                        "service": "imessage",
                        "sms_retry": false,
                        "source": "mac",
                        "source_ref": null,
                        "metadata": {},
                        "hold": null,
                        "send_at": null,
                        "expires_at": null,
                        "failure": null,
                        "cancel_reason": null,
                        "resolution": null,
                        "resolved_at": null,
                        "resent_message_id": null,
                        "reply_to_id": null,
                        "reactions": [],
                        "edited_at": null,
                        "unsent_at": null,
                        "created_at": "2026-11-13T19:44:12.000Z",
                        "queued_at": null,
                        "sending_at": null,
                        "sent_at": null,
                        "delivered_at": null,
                        "read_at": null,
                        "failed_at": null,
                        "unconfirmed_at": null,
                        "expired_at": null,
                        "canceled_at": null,
                        "received_at": "2026-11-13T19:44:10.000Z"
                      }
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/events/{id}": {
      "get": {
        "operationId": "getEvent",
        "summary": "Get an event",
        "description": "One event, as a webhook received it.",
        "tags": [
          "Events"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The event’s id.",
            "schema": {
              "type": "string",
              "pattern": "^evt_[0-9A-Za-z]{22}$"
            },
            "example": "evt_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The event.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                },
                "example": {
                  "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "event",
                  "type": "message.received",
                  "api_version": "2026-11-13",
                  "timestamp": "2026-11-13T19:41:00.000Z",
                  "data": {
                    "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                    "object": "message",
                    "direction": "in",
                    "state": "received",
                    "to": "+15555550100",
                    "from": "+15555550123",
                    "chat_id": null,
                    "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                    "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                    "text": "Perfect, see you there!",
                    "text_deleted": false,
                    "files": [],
                    "service_requested": "auto",
                    "service": "imessage",
                    "sms_retry": false,
                    "source": "mac",
                    "source_ref": null,
                    "metadata": {},
                    "hold": null,
                    "send_at": null,
                    "expires_at": null,
                    "failure": null,
                    "cancel_reason": null,
                    "resolution": null,
                    "resolved_at": null,
                    "resent_message_id": null,
                    "reply_to_id": null,
                    "reactions": [],
                    "edited_at": null,
                    "unsent_at": null,
                    "created_at": "2026-11-13T19:44:12.000Z",
                    "queued_at": null,
                    "sending_at": null,
                    "sent_at": null,
                    "delivered_at": null,
                    "read_at": null,
                    "failed_at": null,
                    "unconfirmed_at": null,
                    "expired_at": null,
                    "canceled_at": null,
                    "received_at": "2026-11-13T19:44:10.000Z"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Every webhook on the account.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of webhooks.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "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": "2026-11-13T19:44:13.000Z",
                      "last_failure_at": null,
                      "last_status": 200,
                      "previous_secret_expires_at": null,
                      "created_at": "2026-11-01T15:10:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Make a webhook",
        "description": "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.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "limit_reached",
          "plan_lapsed",
          "idempotency_conflict",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri",
                    "description": "An https address on the public internet. BlueBot doesn’t follow redirects."
                  },
                  "events": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "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"
                          ]
                        },
                        {
                          "type": "string",
                          "const": "*"
                        }
                      ]
                    },
                    "description": "The event types to send, or `[\"*\"]` for every type, including types BlueBot adds later.",
                    "examples": [
                      [
                        "message.received",
                        "message.failed"
                      ]
                    ]
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200
                  }
                },
                "required": [
                  "url",
                  "events"
                ],
                "description": "A webhook to make."
              },
              "example": {
                "url": "https://hooks.zapier.com/hooks/standard/1234567/abcdef/",
                "events": [
                  "message.received",
                  "message.failed"
                ],
                "description": "New replies to my CRM"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook, with its signing secret.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                },
                "example": {
                  "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"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached. `idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "operationId": "getWebhook",
        "summary": "Get a webhook",
        "description": "One webhook and how its deliveries are going.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "example": {
                  "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": "2026-11-13T19:44:13.000Z",
                  "last_failure_at": null,
                  "last_status": 200,
                  "previous_secret_expires_at": null,
                  "created_at": "2026-11-01T15:10:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWebhook",
        "summary": "Change a webhook",
        "description": "Changes the address, the event types or the description, or pauses or resumes it. Resuming sends what waited from the last 72 hours.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "events": {
                    "description": "Replaces its event types. `[\"*\"]` for every type, including types BlueBot adds later; a list stops new types reaching it.",
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "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"
                          ]
                        },
                        {
                          "type": "string",
                          "const": "*"
                        }
                      ]
                    }
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "paused": {
                    "description": "`true` pauses it; `false` resumes it and sends what waited from the last 72 hours.",
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "paused": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The webhook after the change.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "example": {
                  "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": "paused",
                  "paused_at": "2026-11-13T19:41:00.000Z",
                  "pause_reason": "customer",
                  "failing_since": null,
                  "last_success_at": "2026-11-13T19:44:13.000Z",
                  "last_failure_at": null,
                  "last_status": 200,
                  "previous_secret_expires_at": null,
                  "created_at": "2026-11-01T15:10:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "description": "Deletes the webhook and drops its waiting deliveries.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "It is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "const": "webhook"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ]
                },
                "example": {
                  "id": "wh_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "webhook",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Send a test event",
        "description": "Sends an example event of the type you choose to this webhook alone, signed like a real one, and answers once it was tried. Test events never show in the events feed.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "idempotency_conflict",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "description": "Which event to send an example of. Default `message.received`.",
                    "type": "string",
                    "enum": [
                      "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"
                    ]
                  }
                }
              },
              "example": {
                "type": "message.received"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The delivery, after its first try.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                },
                "example": {
                  "id": "dlv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "webhook_delivery",
                  "webhook_id": "wh_1Hq2LxW9cVbN3mKpRtYs0a",
                  "event_id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                  "event_type": "message.received",
                  "test": true,
                  "state": "delivered",
                  "attempts": 1,
                  "last_status": 200,
                  "last_error": null,
                  "last_duration_ms": 182,
                  "last_response_body": "{\"ok\":true}",
                  "next_attempt_at": null,
                  "delivered_at": "2026-11-13T19:44:13.000Z",
                  "replay_of": null,
                  "created_at": "2026-11-13T19:44:12.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "description": "Makes a new signing secret, shown this once. For 24 hours each delivery is signed with both, so you can switch without missing one.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found",
          "idempotency_conflict",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook, with its new secret.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookWithSecret"
                },
                "example": {
                  "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": "2026-11-13T19:44:13.000Z",
                  "last_failure_at": null,
                  "last_status": 200,
                  "previous_secret_expires_at": "2026-11-14T19:41:00.000Z",
                  "created_at": "2026-11-01T15:10:00.000Z",
                  "secret": "whsec_Zx1q4V8nT2mL6cR0bW9kHs3dPfA7yJuE"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`idempotency_conflict`: Idempotency key reused. `conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "listDeliveries",
        "summary": "List deliveries",
        "description": "What BlueBot tried to deliver to this webhook in the last 30 days, newest first, with each answer’s status.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "gave_up",
                "dropped"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "dlv_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "webhook_delivery",
                      "webhook_id": "wh_1Hq2LxW9cVbN3mKpRtYs0a",
                      "event_id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                      "event_type": "message.received",
                      "test": false,
                      "state": "delivered",
                      "attempts": 1,
                      "last_status": 200,
                      "last_error": null,
                      "last_duration_ms": 182,
                      "last_response_body": "{\"ok\":true}",
                      "next_attempt_at": null,
                      "delivered_at": "2026-11-13T19:44:13.000Z",
                      "replay_of": null,
                      "created_at": "2026-11-13T19:44:12.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/deliveries/{delivery_id}/replay": {
      "post": {
        "operationId": "replayDelivery",
        "summary": "Send a delivery again",
        "description": "Sends the same event to the webhook again as a new delivery, signed afresh. The event keeps its id, so a receiver that already has it can skip it.",
        "tags": [
          "Webhooks"
        ],
        "x-scope": "webhooks:manage",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found",
          "conflict",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The webhook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^wh_[0-9A-Za-z]{22}$"
            },
            "example": "wh_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "description": "The delivery’s id.",
            "schema": {
              "type": "string",
              "pattern": "^dlv_[0-9A-Za-z]{22}$"
            },
            "example": "dlv_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "The new delivery, waiting to be sent.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                },
                "example": {
                  "id": "dlv_2Bf8QzD4kJmA6nXwEuTr1c",
                  "object": "webhook_delivery",
                  "webhook_id": "wh_1Hq2LxW9cVbN3mKpRtYs0a",
                  "event_id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                  "event_type": "message.received",
                  "test": false,
                  "state": "pending",
                  "attempts": 0,
                  "last_status": null,
                  "last_error": null,
                  "last_duration_ms": null,
                  "last_response_body": null,
                  "next_attempt_at": "2026-11-13T19:41:00.000Z",
                  "delivered_at": null,
                  "replay_of": "dlv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "created_at": "2026-11-13T19:44:12.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/contacts": {
      "get": {
        "operationId": "listContacts",
        "summary": "List contacts",
        "description": "Your contacts, the most recently texted first. `q` finds people by name, company, phone number or email, and a few digits of a number work. Filter by `tag`, or by `stopped` for the stop list.",
        "tags": [
          "Contacts"
        ],
        "x-scope": "contacts:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Find people by name, company, phone number or email. Part of one works, and each word can match a different one, so `Dana Oak` finds Dana at Oak Realty.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "Only people with this tag.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            }
          },
          {
            "name": "stopped",
            "in": "query",
            "required": false,
            "description": "`true` for only people on your stop list, `false` for only people who aren’t.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of contacts.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contact"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "contact",
                      "handle": "+15555550123",
                      "kind": "phone",
                      "first_name": "Maria",
                      "last_name": "Alvarez",
                      "company": null,
                      "tags": [
                        "buyer"
                      ],
                      "custom_fields": {
                        "showing": "412 Oak St"
                      },
                      "stopped": false,
                      "stopped_at": null,
                      "stop_source": null,
                      "last_service": "imessage",
                      "first_message_at": "2026-11-02T15:20:00.000Z",
                      "last_message_at": "2026-11-13T19:41:00.000Z",
                      "created_via": "message",
                      "created_at": "2026-11-02T15:20:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createContact",
        "summary": "Add a contact",
        "description": "Adds a person with their name, tags and custom fields, which templates fill in. Somebody you text is added on their own, so this is for adding details ahead of time. A handle that is already a contact answers `conflict`; change that contact with `PATCH /v1/contacts/{id}` instead.",
        "tags": [
          "Contacts"
        ],
        "x-scope": "contacts:write",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "conflict",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320,
                    "description": "Their phone number (US numbers may leave off +1) or the email address their Apple ID uses.",
                    "examples": [
                      "+15555550123"
                    ]
                  },
                  "first_name": {
                    "description": "The first name. Send null or an empty string to clear it.",
                    "examples": [
                      "Maria"
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "last_name": {
                    "description": "The last name. Send null or an empty string to clear it.",
                    "examples": [
                      "Alvarez"
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "company": {
                    "description": "The company. Send null or an empty string to clear it.",
                    "examples": [
                      null
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "tags": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    },
                    "description": "Tags, at most 50 of up to 50 characters each. Capitals are kept but a tag counts once however it is spelled.",
                    "examples": [
                      [
                        "buyer",
                        "oak-st"
                      ]
                    ]
                  },
                  "custom_fields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own fields for templates, at most 50. Names are made template-safe (`Showing address` becomes `showing_address`); an empty value drops the field.",
                    "examples": [
                      {
                        "showing": "412 Oak St"
                      }
                    ]
                  }
                },
                "required": [
                  "handle"
                ]
              },
              "example": {
                "handle": "+15555550123",
                "first_name": "Maria",
                "last_name": "Alvarez",
                "tags": [
                  "buyer"
                ],
                "custom_fields": {
                  "showing": "412 Oak St"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new contact.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer"
                  ],
                  "custom_fields": {
                    "showing": "412 Oak St"
                  },
                  "stopped": false,
                  "stopped_at": null,
                  "stop_source": null,
                  "last_service": null,
                  "first_message_at": null,
                  "last_message_at": null,
                  "created_via": "api",
                  "created_at": "2026-11-02T15:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "operationId": "getContact",
        "summary": "Get a contact",
        "description": "One contact, with their tags, custom fields and whether they are on your stop list.",
        "tags": [
          "Contacts"
        ],
        "x-scope": "contacts:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact’s id.",
            "schema": {
              "type": "string",
              "pattern": "^ct_[0-9A-Za-z]{22}$"
            },
            "example": "ct_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The contact.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer"
                  ],
                  "custom_fields": {
                    "showing": "412 Oak St"
                  },
                  "stopped": false,
                  "stopped_at": null,
                  "stop_source": null,
                  "last_service": "imessage",
                  "first_message_at": "2026-11-02T15:20:00.000Z",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_via": "message",
                  "created_at": "2026-11-02T15:20:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateContact",
        "summary": "Change a contact",
        "description": "Changes the fields you send and leaves the rest. `tags` and `custom_fields` replace the whole list or set. The handle can’t change, since the contact’s texts are filed under it. Use the stop list operations to stop or start texting somebody.",
        "tags": [
          "Contacts"
        ],
        "x-scope": "contacts:write",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact’s id.",
            "schema": {
              "type": "string",
              "pattern": "^ct_[0-9A-Za-z]{22}$"
            },
            "example": "ct_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "description": "The first name. Send null or an empty string to clear it.",
                    "examples": [
                      "Maria"
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "last_name": {
                    "description": "The last name. Send null or an empty string to clear it.",
                    "examples": [
                      "Alvarez"
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 100
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "company": {
                    "description": "The company. Send null or an empty string to clear it.",
                    "examples": [
                      null
                    ],
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "tags": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 50
                    },
                    "description": "Tags, at most 50 of up to 50 characters each. Capitals are kept but a tag counts once however it is spelled.",
                    "examples": [
                      [
                        "buyer",
                        "oak-st"
                      ]
                    ]
                  },
                  "custom_fields": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    },
                    "description": "Your own fields for templates, at most 50. Names are made template-safe (`Showing address` becomes `showing_address`); an empty value drops the field.",
                    "examples": [
                      {
                        "showing": "412 Oak St"
                      }
                    ]
                  }
                }
              },
              "example": {
                "tags": [
                  "buyer",
                  "closed"
                ],
                "custom_fields": {
                  "showing": "412 Oak St",
                  "closing": "Dec 3"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The contact after the change.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                },
                "example": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer",
                    "closed"
                  ],
                  "custom_fields": {
                    "showing": "412 Oak St",
                    "closing": "Dec 3"
                  },
                  "stopped": false,
                  "stopped_at": null,
                  "stop_source": null,
                  "last_service": "imessage",
                  "first_message_at": "2026-11-02T15:20:00.000Z",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_via": "message",
                  "created_at": "2026-11-02T15:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteContact",
        "summary": "Delete a contact",
        "description": "Takes the person off your contacts. Their texts stay in your history, and a stop stays with their number: a text to or from them later adds them back, still on the stop list if they were.",
        "tags": [
          "Contacts"
        ],
        "x-scope": "contacts:write",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The contact’s id.",
            "schema": {
              "type": "string",
              "pattern": "^ct_[0-9A-Za-z]{22}$"
            },
            "example": "ct_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The contact is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "const": "contact"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ]
                },
                "example": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/templates": {
      "get": {
        "operationId": "listTemplates",
        "summary": "List templates",
        "description": "Your saved texts, newest first, with the variables each one names. `q` finds them by name.",
        "tags": [
          "Templates"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Only templates whose name or words have this in them.",
            "schema": {
              "type": "string",
              "maxLength": 80
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of templates.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Template"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "tpl_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "template",
                      "name": "Showing reminder",
                      "body": "Hi {{first_name|there}}, see you at {{showing}} tomorrow.",
                      "variables": [
                        "first_name",
                        "showing"
                      ],
                      "created_at": "2026-11-10T16:00:00.000Z",
                      "updated_at": "2026-11-10T16:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createTemplate",
        "summary": "Make a template",
        "description": "Saves a text with `{{variables}}`. A variable is a contact field (`first_name`, `last_name`, `company`), one of their custom fields, or a value you pass when sending; `{{first_name|there}}` uses “there” when the contact has no first name. A variable that is empty with no fallback is left out, along with the space before it.",
        "tags": [
          "Templates"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "conflict",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "A name, unique among your templates whatever its capitals."
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "The text, up to 2,000 characters, with `{{variables}}` and `{{variable|fallback}}`."
                  }
                },
                "required": [
                  "name",
                  "body"
                ]
              },
              "example": {
                "name": "Showing reminder",
                "body": "Hi {{first_name|there}}, see you at {{showing}} tomorrow."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new template.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "example": {
                  "id": "tpl_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "template",
                  "name": "Showing reminder",
                  "body": "Hi {{first_name|there}}, see you at {{showing}} tomorrow.",
                  "variables": [
                    "first_name",
                    "showing"
                  ],
                  "created_at": "2026-11-10T16:00:00.000Z",
                  "updated_at": "2026-11-10T16:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/templates/{id}": {
      "get": {
        "operationId": "getTemplate",
        "summary": "Get a template",
        "description": "One template and the variables it names.",
        "tags": [
          "Templates"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The template’s id.",
            "schema": {
              "type": "string",
              "pattern": "^tpl_[0-9A-Za-z]{22}$"
            },
            "example": "tpl_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The template.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "example": {
                  "id": "tpl_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "template",
                  "name": "Showing reminder",
                  "body": "Hi {{first_name|there}}, see you at {{showing}} tomorrow.",
                  "variables": [
                    "first_name",
                    "showing"
                  ],
                  "created_at": "2026-11-10T16:00:00.000Z",
                  "updated_at": "2026-11-10T16:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTemplate",
        "summary": "Change a template",
        "description": "Changes the name, the text or both. Sequences and keyword replies that use it send the new text from their next text on.",
        "tags": [
          "Templates"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "conflict"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The template’s id.",
            "schema": {
              "type": "string",
              "pattern": "^tpl_[0-9A-Za-z]{22}$"
            },
            "example": "tpl_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "A name, unique among your templates whatever its capitals."
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "The text, up to 2,000 characters, with `{{variables}}` and `{{variable|fallback}}`."
                  }
                }
              },
              "example": {
                "body": "Hi {{first_name|there}}, a reminder that we see {{showing}} tomorrow at 10."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The template after the change.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                },
                "example": {
                  "id": "tpl_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "template",
                  "name": "Showing reminder",
                  "body": "Hi {{first_name|there}}, a reminder that we see {{showing}} tomorrow at 10.",
                  "variables": [
                    "first_name",
                    "showing"
                  ],
                  "created_at": "2026-11-10T16:00:00.000Z",
                  "updated_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTemplate",
        "summary": "Delete a template",
        "description": "Deletes the template, and its name is free to use again. Texts already sent with it are unchanged.",
        "tags": [
          "Templates"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The template’s id.",
            "schema": {
              "type": "string",
              "pattern": "^tpl_[0-9A-Za-z]{22}$"
            },
            "example": "tpl_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The template is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "const": "template"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ]
                },
                "example": {
                  "id": "tpl_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "template",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/analytics": {
      "get": {
        "operationId": "getAnalytics",
        "summary": "Get the numbers",
        "description": "Counts for the last 7, 30 or 90 days, ending now and read in your time zone: texts in and out by day and by hour, delivery and reply rates, how long people take to answer you and how long you take to answer them, iMessage against SMS, where texts came from, and the conversations waiting on you with what to fix next. The numbers on the dashboard’s Analytics page.\n\n`delivery_rate` is texts that reported delivered or read, out of texts that left the Mac or failed; canceled, expired, waiting and unconfirmed texts aren’t counted, and a regular text that never reports delivery counts as sent. `reply_rate` is people you texted one to one who texted back within `reply_window_hours`. Response times are medians over one-to-one conversations, counting a reply only within seven days.",
        "tags": [
          "Analytics"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "How many days to cover, ending today in your time zone: 7, 30 or 90. Default 30.",
            "schema": {
              "default": 30,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The numbers.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Analytics"
                },
                "example": {
                  "object": "analytics",
                  "days": 7,
                  "time_zone": "America/Chicago",
                  "from": "2026-11-07T06:00:00.000Z",
                  "to": "2026-11-13T19:41:00.000Z",
                  "first_text_at": "2026-09-02T16:20:00.000Z",
                  "totals": {
                    "sent": 182,
                    "received": 96,
                    "delivered": 171,
                    "read": 120,
                    "failed": 3,
                    "unconfirmed": 0,
                    "canceled": 4,
                    "expired": 1,
                    "people_texted": 64,
                    "people_replied": 41,
                    "new_people": 22,
                    "stops": 1
                  },
                  "delivery_rate": 0.9243,
                  "reply_rate": 0.6406,
                  "reply_window_hours": 72,
                  "response_times": {
                    "them_median_seconds": 1260,
                    "them_count": 58,
                    "you_median_seconds": 540,
                    "you_count": 37
                  },
                  "services": {
                    "imessage": 151,
                    "sms": 31
                  },
                  "by_day": [
                    {
                      "day": "2026-11-07",
                      "sent": 20,
                      "received": 9
                    }
                  ],
                  "by_hour": [
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ],
                    [
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0,
                      0
                    ]
                  ],
                  "by_source": [
                    {
                      "source": "zapier",
                      "count": 104
                    },
                    {
                      "source": "inbox",
                      "count": 61
                    },
                    {
                      "source": "sequence",
                      "count": 17
                    }
                  ],
                  "health": {
                    "waiting": 3,
                    "follow_up_gaps": 1,
                    "oldest_waiting_at": "2026-11-10T15:02:00.000Z",
                    "waiting_list": [
                      {
                        "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                        "name": "Marcus Lee",
                        "handle": "+15555550123",
                        "is_group": false,
                        "since": "2026-11-10T15:02:00.000Z",
                        "follow_up_gap": true
                      }
                    ],
                    "unconfirmed": 0,
                    "held": 2
                  },
                  "fixes": [
                    {
                      "key": "follow_up_gaps",
                      "title": "1 person answered you and hasn’t heard back in two days.",
                      "why": "A reply that waits days often goes cold.",
                      "count": 1,
                      "href": "/app/inbox?filter=waiting",
                      "severity": "high"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "operationId": "listConversations",
        "summary": "List conversations",
        "description": "Your conversations as the dashboard’s inbox shows them, one per person or group chat, the most recent first. `filter` narrows to `unread`, `waiting` (the last text is theirs) or `archived`, and `q` searches names, numbers, group names and the words of texts.",
        "tags": [
          "Conversations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search names, numbers, group names and the words of texts.",
            "schema": {
              "type": "string",
              "maxLength": 100
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "description": "`all` (not archived), `unread`, `waiting` (the last text is theirs) or `archived`.",
            "schema": {
              "default": "all",
              "type": "string",
              "enum": [
                "all",
                "unread",
                "waiting",
                "archived"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of conversations.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "conversation",
                      "kind": "person",
                      "title": "Maria Alvarez",
                      "handle": "+15555550123",
                      "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "chat_id": null,
                      "participants": [
                        "+15555550123"
                      ],
                      "service": "imessage",
                      "last_message": {
                        "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                        "direction": "in",
                        "state": "received",
                        "preview": "Can we move the showing to 4?",
                        "files": 0,
                        "at": "2026-11-13T19:44:12.000Z"
                      },
                      "last_message_at": "2026-11-13T19:44:12.000Z",
                      "unread_count": 1,
                      "waiting": true,
                      "archived": false,
                      "stopped": false,
                      "created_at": "2026-11-02T15:20:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{id}": {
      "get": {
        "operationId": "getConversation",
        "summary": "Get a conversation",
        "description": "One conversation with its last text, how many texts in are unread, and whether the person is waiting on you.",
        "tags": [
          "Conversations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation’s id.",
            "schema": {
              "type": "string",
              "pattern": "^conv_[0-9A-Za-z]{22}$"
            },
            "example": "conv_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The conversation.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "conversation",
                  "kind": "person",
                  "title": "Maria Alvarez",
                  "handle": "+15555550123",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "chat_id": null,
                  "participants": [
                    "+15555550123"
                  ],
                  "service": "imessage",
                  "last_message": {
                    "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                    "direction": "in",
                    "state": "received",
                    "preview": "Can we move the showing to 4?",
                    "files": 0,
                    "at": "2026-11-13T19:44:12.000Z"
                  },
                  "last_message_at": "2026-11-13T19:44:12.000Z",
                  "unread_count": 1,
                  "waiting": true,
                  "archived": false,
                  "stopped": false,
                  "created_at": "2026-11-02T15:20:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateConversation",
        "summary": "Mark a conversation read or done",
        "description": "`read: true` marks every text in it read in the dashboard. `archived: true` marks it done, which also marks it read, and `archived: false` brings it back. A new text in brings an archived conversation back on its own.",
        "tags": [
          "Conversations"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation’s id.",
            "schema": {
              "type": "string",
              "pattern": "^conv_[0-9A-Za-z]{22}$"
            },
            "example": "conv_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "read": {
                    "description": "True marks every text in it read.",
                    "type": "boolean"
                  },
                  "archived": {
                    "description": "True marks it done; false brings it back.",
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "archived": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The conversation after the change.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Conversation"
                },
                "example": {
                  "id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "conversation",
                  "kind": "person",
                  "title": "Maria Alvarez",
                  "handle": "+15555550123",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "chat_id": null,
                  "participants": [
                    "+15555550123"
                  ],
                  "service": "imessage",
                  "last_message": {
                    "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                    "direction": "in",
                    "state": "received",
                    "preview": "Can we move the showing to 4?",
                    "files": 0,
                    "at": "2026-11-13T19:44:12.000Z"
                  },
                  "last_message_at": "2026-11-13T19:44:12.000Z",
                  "unread_count": 0,
                  "waiting": true,
                  "archived": true,
                  "stopped": false,
                  "created_at": "2026-11-02T15:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/conversations/{id}/messages": {
      "get": {
        "operationId": "listConversationMessages",
        "summary": "List a conversation’s texts",
        "description": "The texts in one conversation, in and out, newest first. Page back with `cursor` to read further.",
        "tags": [
          "Conversations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation’s id.",
            "schema": {
              "type": "string",
              "pattern": "^conv_[0-9A-Za-z]{22}$"
            },
            "example": "conv_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of texts, newest first.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "message",
                      "direction": "out",
                      "state": "sent",
                      "to": "+15555550123",
                      "from": "+15555550100",
                      "chat_id": null,
                      "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                      "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                      "text_deleted": false,
                      "files": [],
                      "service_requested": "auto",
                      "service": "imessage",
                      "sms_retry": false,
                      "source": "api",
                      "source_ref": null,
                      "metadata": {
                        "crm_id": "48213"
                      },
                      "hold": null,
                      "send_at": null,
                      "expires_at": "2026-11-14T19:41:00.000Z",
                      "failure": null,
                      "cancel_reason": null,
                      "resolution": null,
                      "resolved_at": null,
                      "resent_message_id": null,
                      "reply_to_id": null,
                      "reactions": [],
                      "edited_at": null,
                      "unsent_at": null,
                      "created_at": "2026-11-13T19:41:00.000Z",
                      "queued_at": "2026-11-13T19:41:00.000Z",
                      "sending_at": "2026-11-13T19:41:02.000Z",
                      "sent_at": "2026-11-13T19:41:05.000Z",
                      "delivered_at": null,
                      "read_at": null,
                      "failed_at": null,
                      "unconfirmed_at": null,
                      "expired_at": null,
                      "canceled_at": null,
                      "received_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/broadcasts": {
      "post": {
        "operationId": "createBroadcast",
        "summary": "Send a broadcast",
        "description": "Sends one text to up to 500 people: contacts with any of `tags`, the contacts in `contact_ids`, or a list in `recipients` (people who aren’t contacts yet are added). Each person’s `{{variables}}` are filled in from their contact and their row.\n\nTexts go through your sending rules like any other: your pace, quiet hours, the daily limit for new people and BlueBot’s daily limit. BlueBot feeds them into the queue a few at a time, so a long broadcast never sits in the queue long enough to expire. People on your stop list are skipped. `estimate` says when the last text should go.\n\nOnly send to people who asked to hear from you.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "limit_reached",
          "plan_lapsed",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "The words. `{{first_name}}`, `{{first_name|there}}` and any variable your list brings are filled in for each person."
                  },
                  "template_id": {
                    "type": "string",
                    "pattern": "^tpl_[0-9A-Za-z]{22}$",
                    "description": "A saved template to use instead of `text`."
                  },
                  "tags": {
                    "description": "Send to your contacts with any of these tags.",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    }
                  },
                  "contact_ids": {
                    "description": "Send to these contacts.",
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^ct_[0-9A-Za-z]{22}$",
                      "description": "A ct_ id.",
                      "examples": [
                        "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    }
                  },
                  "recipients": {
                    "description": "Send to these people, adding any who aren’t contacts yet, each with their own variables.",
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "to": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 320,
                          "description": "A phone number (US numbers may leave off +1; `(555) 555-0123` works) or an email address an Apple ID uses.",
                          "examples": [
                            "+15555550123"
                          ]
                        },
                        "first_name": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "variables": {
                          "description": "Values for this person’s `{{variables}}`.",
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 60
                          },
                          "additionalProperties": {
                            "type": "string",
                            "maxLength": 500
                          }
                        }
                      },
                      "required": [
                        "to"
                      ]
                    }
                  },
                  "service": {
                    "default": "auto",
                    "type": "string",
                    "enum": [
                      "auto",
                      "imessage",
                      "sms"
                    ]
                  },
                  "send_at": {
                    "description": "Start later. Leave it out to start now.",
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "name"
                ],
                "description": "A broadcast to start now or at `send_at`."
              },
              "example": {
                "name": "Open house Saturday",
                "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
                "tags": [
                  "buyer"
                ],
                "send_at": "2026-11-14T15:00:00.000Z"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The broadcast, started or scheduled.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "broadcast",
                  "name": "Open house Saturday",
                  "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
                  "text_deleted": false,
                  "template_id": null,
                  "audience": {
                    "kind": "tags",
                    "tags": [
                      "buyer"
                    ]
                  },
                  "service": "auto",
                  "state": "scheduled",
                  "send_at": "2026-11-14T15:00:00.000Z",
                  "started_at": null,
                  "completed_at": null,
                  "canceled_at": null,
                  "recipient_count": 42,
                  "counts": {
                    "pending": 41,
                    "skipped": 1
                  },
                  "estimate": {
                    "first_at": "2026-11-14T15:00:00.000Z",
                    "last_at": "2026-11-14T15:14:20.000Z",
                    "days": 1,
                    "waits_for": [],
                    "blocked_by": null,
                    "mac_online": true
                  },
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listBroadcasts",
        "summary": "List broadcasts",
        "description": "Your broadcasts, newest first.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Only broadcasts in this state.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "sending",
                "completed",
                "canceled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of broadcasts.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Broadcast"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "broadcast",
                      "name": "Open house Saturday",
                      "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
                      "text_deleted": false,
                      "template_id": null,
                      "audience": {
                        "kind": "tags",
                        "tags": [
                          "buyer"
                        ]
                      },
                      "service": "auto",
                      "state": "scheduled",
                      "send_at": "2026-11-14T15:00:00.000Z",
                      "started_at": null,
                      "completed_at": null,
                      "canceled_at": null,
                      "recipient_count": 42,
                      "counts": {
                        "pending": 41,
                        "skipped": 1
                      },
                      "estimate": null,
                      "created_via": "api",
                      "created_at": "2026-11-13T19:41:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/broadcasts/preview": {
      "post": {
        "operationId": "previewBroadcast",
        "summary": "Check a broadcast before sending it",
        "description": "Answers what `POST /v1/broadcasts` would do with the same body, without sending anything: how many people it reaches, who is skipped, the first five texts filled in, and when the last one should go.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "limit_reached"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "The words."
                  },
                  "template_id": {
                    "type": "string",
                    "pattern": "^tpl_[0-9A-Za-z]{22}$",
                    "description": "A saved template to use instead of `text`."
                  },
                  "tags": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    }
                  },
                  "contact_ids": {
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^ct_[0-9A-Za-z]{22}$",
                      "description": "A ct_ id.",
                      "examples": [
                        "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    }
                  },
                  "recipients": {
                    "maxItems": 500,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "to": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 320,
                          "description": "A phone number (US numbers may leave off +1; `(555) 555-0123` works) or an email address an Apple ID uses.",
                          "examples": [
                            "+15555550123"
                          ]
                        },
                        "first_name": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "last_name": {
                          "type": "string",
                          "maxLength": 100
                        },
                        "variables": {
                          "description": "Values for this person’s `{{variables}}`.",
                          "type": "object",
                          "propertyNames": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 60
                          },
                          "additionalProperties": {
                            "type": "string",
                            "maxLength": 500
                          }
                        }
                      },
                      "required": [
                        "to"
                      ]
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "description": "A broadcast to check before sending it."
              },
              "example": {
                "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4.",
                "tags": [
                  "buyer"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What it would do.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BroadcastPreview"
                },
                "example": {
                  "object": "broadcast_preview",
                  "recipient_count": 42,
                  "stopped_count": 1,
                  "new_people_count": 3,
                  "duplicate_count": 0,
                  "samples": [
                    {
                      "handle": "+15555550123",
                      "name": "Maria Alvarez",
                      "text": "Hi Maria, open house at 412 Oak St this Saturday 1–4.",
                      "missing": []
                    }
                  ],
                  "estimate": {
                    "first_at": "2026-11-14T15:00:00.000Z",
                    "last_at": "2026-11-14T15:14:20.000Z",
                    "days": 1,
                    "waits_for": [],
                    "blocked_by": null,
                    "mac_online": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/broadcasts/{id}": {
      "get": {
        "operationId": "getBroadcast",
        "summary": "Get a broadcast",
        "description": "One broadcast with its counts and, while it is sending, when the rest should go.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The broadcast’s id.",
            "schema": {
              "type": "string",
              "pattern": "^bc_[0-9A-Za-z]{22}$"
            },
            "example": "bc_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The broadcast.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "broadcast",
                  "name": "Open house Saturday",
                  "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
                  "text_deleted": false,
                  "template_id": null,
                  "audience": {
                    "kind": "tags",
                    "tags": [
                      "buyer"
                    ]
                  },
                  "service": "auto",
                  "state": "scheduled",
                  "send_at": "2026-11-14T15:00:00.000Z",
                  "started_at": null,
                  "completed_at": null,
                  "canceled_at": null,
                  "recipient_count": 42,
                  "counts": {
                    "pending": 41,
                    "skipped": 1
                  },
                  "estimate": {
                    "first_at": "2026-11-14T15:00:00.000Z",
                    "last_at": "2026-11-14T15:14:20.000Z",
                    "days": 1,
                    "waits_for": [],
                    "blocked_by": null,
                    "mac_online": true
                  },
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/broadcasts/{id}/recipients": {
      "get": {
        "operationId": "listBroadcastRecipients",
        "summary": "List a broadcast’s recipients",
        "description": "Each person in a broadcast with where their text stands.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The broadcast’s id.",
            "schema": {
              "type": "string",
              "pattern": "^bc_[0-9A-Za-z]{22}$"
            },
            "example": "bc_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Only recipients in this state.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "queued",
                "skipped",
                "sent",
                "delivered",
                "read",
                "failed",
                "unconfirmed",
                "expired",
                "canceled"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of recipients.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BroadcastRecipient"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "broadcast_recipient",
                      "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "handle": "+15555550123",
                      "name": "Maria Alvarez",
                      "state": "delivered",
                      "skip_reason": null,
                      "message_id": "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/broadcasts/{id}/cancel": {
      "post": {
        "operationId": "cancelBroadcast",
        "summary": "Cancel the rest of a broadcast",
        "description": "Nobody still waiting gets their text, and texts queued but not yet taken by your Mac are canceled. Texts already sent stay sent. `broadcast.completed` fires with `state: \"canceled\"`.",
        "tags": [
          "Broadcasts"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The broadcast’s id.",
            "schema": {
              "type": "string",
              "pattern": "^bc_[0-9A-Za-z]{22}$"
            },
            "example": "bc_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The broadcast, canceled.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Broadcast"
                },
                "example": {
                  "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "broadcast",
                  "name": "Open house Saturday",
                  "text": "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4. Reply STOP to opt out.",
                  "text_deleted": false,
                  "template_id": null,
                  "audience": {
                    "kind": "tags",
                    "tags": [
                      "buyer"
                    ]
                  },
                  "service": "auto",
                  "state": "canceled",
                  "send_at": "2026-11-14T15:00:00.000Z",
                  "started_at": null,
                  "completed_at": null,
                  "canceled_at": "2026-11-13T19:41:00.000Z",
                  "recipient_count": 42,
                  "counts": {
                    "sent": 20,
                    "canceled": 21,
                    "skipped": 1
                  },
                  "estimate": null,
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "That text was already sent, so it can’t be canceled.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sequences": {
      "post": {
        "operationId": "createSequence",
        "summary": "Make a sequence",
        "description": "A sequence is texts with waits between them. Each person added runs through it on their own, and stops when they text back (unless `stop_on_reply` is off) or text STOP. With `send_window`, a text due outside it waits for the window to open.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "limit_reached",
          "plan_lapsed",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "stop_on_reply": {
                    "default": true,
                    "type": "boolean"
                  },
                  "send_window": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "days": {
                            "minItems": 1,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "mon",
                                "tue",
                                "wed",
                                "thu",
                                "fri",
                                "sat",
                                "sun"
                              ]
                            },
                            "description": "The days it may send on."
                          },
                          "start": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "A time of day as HH:MM in your account’s time zone."
                          },
                          "end": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "A time of day as HH:MM in your account’s time zone."
                          }
                        },
                        "required": [
                          "days",
                          "start",
                          "end"
                        ],
                        "description": "When steps may send, in your time zone. A step due outside it waits for it to open."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "steps": {
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "text"
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2000,
                              "description": "The words, with `{{variables}}`."
                            },
                            "template_id": {
                              "type": "string",
                              "pattern": "^tpl_[0-9A-Za-z]{22}$",
                              "description": "A saved template to use instead of `text`."
                            },
                            "service": {
                              "default": "auto",
                              "type": "string",
                              "enum": [
                                "auto",
                                "imessage",
                                "sms"
                              ]
                            }
                          },
                          "required": [
                            "kind"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "wait"
                            },
                            "wait_seconds": {
                              "type": "integer",
                              "minimum": 60,
                              "maximum": 31536000,
                              "description": "How long to wait, in seconds: 3600 is an hour, 86400 a day."
                            }
                          },
                          "required": [
                            "kind",
                            "wait_seconds"
                          ]
                        }
                      ]
                    },
                    "description": "The steps in order."
                  }
                },
                "required": [
                  "name",
                  "steps"
                ],
                "description": "A sequence to make."
              },
              "example": {
                "name": "New lead follow-up",
                "steps": [
                  {
                    "kind": "text",
                    "text": "Hi {{first_name|there}}, thanks for asking about {{listing}}. Want to see it?"
                  },
                  {
                    "kind": "wait",
                    "wait_seconds": 172800
                  },
                  {
                    "kind": "text",
                    "text": "Just checking in. Still interested in {{listing}}?"
                  }
                ],
                "send_window": {
                  "days": [
                    "mon",
                    "tue",
                    "wed",
                    "thu",
                    "fri"
                  ],
                  "start": "09:00",
                  "end": "18:00"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The sequence.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sequence"
                },
                "example": {
                  "id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "sequence",
                  "name": "New lead follow-up",
                  "description": "For people who ask about a listing.",
                  "state": "active",
                  "stop_on_reply": true,
                  "send_window": {
                    "days": [
                      "mon",
                      "tue",
                      "wed",
                      "thu",
                      "fri"
                    ],
                    "start": "09:00",
                    "end": "18:00"
                  },
                  "steps": [
                    {
                      "id": "step_1Hq2LxW9cVbN3mKpRtYs0a",
                      "position": 0,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Hi {{first_name|there}}, thanks for asking about {{listing}}. Want to see it?",
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_2Bf8QzD4kJmA6nXwEuTr1c",
                      "position": 1,
                      "kind": "wait",
                      "wait_seconds": 172800,
                      "text": null,
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_3Lp3VsC7hGqE5tZyKbWn2d",
                      "position": 2,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Just checking in. Still interested in {{listing}}?",
                      "template_id": null,
                      "service": "auto"
                    }
                  ],
                  "counts": {},
                  "created_via": "dashboard",
                  "created_at": "2026-11-01T15:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listSequences",
        "summary": "List sequences",
        "description": "Your sequences, newest first. Archived ones are left out unless you ask for `state=archived`.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "state",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "archived"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of sequences.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Sequence"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "sequence",
                      "name": "New lead follow-up",
                      "description": "For people who ask about a listing.",
                      "state": "active",
                      "stop_on_reply": true,
                      "send_window": {
                        "days": [
                          "mon",
                          "tue",
                          "wed",
                          "thu",
                          "fri"
                        ],
                        "start": "09:00",
                        "end": "18:00"
                      },
                      "steps": [
                        {
                          "id": "step_1Hq2LxW9cVbN3mKpRtYs0a",
                          "position": 0,
                          "kind": "text",
                          "wait_seconds": null,
                          "text": "Hi {{first_name|there}}, thanks for asking about {{listing}}. Want to see it?",
                          "template_id": null,
                          "service": "auto"
                        },
                        {
                          "id": "step_2Bf8QzD4kJmA6nXwEuTr1c",
                          "position": 1,
                          "kind": "wait",
                          "wait_seconds": 172800,
                          "text": null,
                          "template_id": null,
                          "service": "auto"
                        },
                        {
                          "id": "step_3Lp3VsC7hGqE5tZyKbWn2d",
                          "position": 2,
                          "kind": "text",
                          "wait_seconds": null,
                          "text": "Just checking in. Still interested in {{listing}}?",
                          "template_id": null,
                          "service": "auto"
                        }
                      ],
                      "counts": {
                        "active": 12,
                        "completed": 30,
                        "stopped": 9,
                        "canceled": 1
                      },
                      "created_via": "dashboard",
                      "created_at": "2026-11-01T15:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sequences/{id}": {
      "get": {
        "operationId": "getSequence",
        "summary": "Get a sequence",
        "description": "One sequence with its steps and how many people are in each state.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The sequence’s id.",
            "schema": {
              "type": "string",
              "pattern": "^seq_[0-9A-Za-z]{22}$"
            },
            "example": "seq_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The sequence.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sequence"
                },
                "example": {
                  "id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "sequence",
                  "name": "New lead follow-up",
                  "description": "For people who ask about a listing.",
                  "state": "active",
                  "stop_on_reply": true,
                  "send_window": {
                    "days": [
                      "mon",
                      "tue",
                      "wed",
                      "thu",
                      "fri"
                    ],
                    "start": "09:00",
                    "end": "18:00"
                  },
                  "steps": [
                    {
                      "id": "step_1Hq2LxW9cVbN3mKpRtYs0a",
                      "position": 0,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Hi {{first_name|there}}, thanks for asking about {{listing}}. Want to see it?",
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_2Bf8QzD4kJmA6nXwEuTr1c",
                      "position": 1,
                      "kind": "wait",
                      "wait_seconds": 172800,
                      "text": null,
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_3Lp3VsC7hGqE5tZyKbWn2d",
                      "position": 2,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Just checking in. Still interested in {{listing}}?",
                      "template_id": null,
                      "service": "auto"
                    }
                  ],
                  "counts": {
                    "active": 12,
                    "completed": 30,
                    "stopped": 9,
                    "canceled": 1
                  },
                  "created_via": "dashboard",
                  "created_at": "2026-11-01T15:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateSequence",
        "summary": "Change a sequence",
        "description": "Renames it, pauses or resumes it, archives it (which ends every active run), or replaces its steps. People already in it carry on from the step number they reached.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The sequence’s id.",
            "schema": {
              "type": "string",
              "pattern": "^seq_[0-9A-Za-z]{22}$"
            },
            "example": "seq_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "state": {
                    "description": "Pause, resume or archive it. Archiving ends every active enrollment.",
                    "type": "string",
                    "enum": [
                      "active",
                      "paused",
                      "archived"
                    ]
                  },
                  "stop_on_reply": {
                    "type": "boolean"
                  },
                  "send_window": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "days": {
                            "minItems": 1,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "enum": [
                                "mon",
                                "tue",
                                "wed",
                                "thu",
                                "fri",
                                "sat",
                                "sun"
                              ]
                            },
                            "description": "The days it may send on."
                          },
                          "start": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "A time of day as HH:MM in your account’s time zone."
                          },
                          "end": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                            "description": "A time of day as HH:MM in your account’s time zone."
                          }
                        },
                        "required": [
                          "days",
                          "start",
                          "end"
                        ],
                        "description": "When steps may send, in your time zone. A step due outside it waits for it to open."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "steps": {
                    "description": "Replaces every step. People already in it carry on from the step number they reached.",
                    "minItems": 1,
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "text"
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2000,
                              "description": "The words, with `{{variables}}`."
                            },
                            "template_id": {
                              "type": "string",
                              "pattern": "^tpl_[0-9A-Za-z]{22}$",
                              "description": "A saved template to use instead of `text`."
                            },
                            "service": {
                              "default": "auto",
                              "type": "string",
                              "enum": [
                                "auto",
                                "imessage",
                                "sms"
                              ]
                            }
                          },
                          "required": [
                            "kind"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "kind": {
                              "type": "string",
                              "const": "wait"
                            },
                            "wait_seconds": {
                              "type": "integer",
                              "minimum": 60,
                              "maximum": 31536000,
                              "description": "How long to wait, in seconds: 3600 is an hour, 86400 a day."
                            }
                          },
                          "required": [
                            "kind",
                            "wait_seconds"
                          ]
                        }
                      ]
                    }
                  }
                }
              },
              "example": {
                "state": "paused"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed sequence.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sequence"
                },
                "example": {
                  "id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "sequence",
                  "name": "New lead follow-up",
                  "description": "For people who ask about a listing.",
                  "state": "paused",
                  "stop_on_reply": true,
                  "send_window": {
                    "days": [
                      "mon",
                      "tue",
                      "wed",
                      "thu",
                      "fri"
                    ],
                    "start": "09:00",
                    "end": "18:00"
                  },
                  "steps": [
                    {
                      "id": "step_1Hq2LxW9cVbN3mKpRtYs0a",
                      "position": 0,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Hi {{first_name|there}}, thanks for asking about {{listing}}. Want to see it?",
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_2Bf8QzD4kJmA6nXwEuTr1c",
                      "position": 1,
                      "kind": "wait",
                      "wait_seconds": 172800,
                      "text": null,
                      "template_id": null,
                      "service": "auto"
                    },
                    {
                      "id": "step_3Lp3VsC7hGqE5tZyKbWn2d",
                      "position": 2,
                      "kind": "text",
                      "wait_seconds": null,
                      "text": "Just checking in. Still interested in {{listing}}?",
                      "template_id": null,
                      "service": "auto"
                    }
                  ],
                  "counts": {
                    "active": 12,
                    "completed": 30,
                    "stopped": 9,
                    "canceled": 1
                  },
                  "created_via": "dashboard",
                  "created_at": "2026-11-01T15:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sequences/{id}/enrollments": {
      "post": {
        "operationId": "enrollInSequence",
        "summary": "Add a person to a sequence",
        "description": "Starts the sequence for one person, by `to` (added as a contact when new) or `contact_id`. A person can be in a sequence once at a time: adding somebody already in it answers `conflict`, and so does adding somebody on your stop list or a sequence that is archived.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "conflict",
          "plan_lapsed",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The sequence’s id.",
            "schema": {
              "type": "string",
              "pattern": "^seq_[0-9A-Za-z]{22}$"
            },
            "example": "seq_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "description": "The person to add. Send `to` or `contact_id`.",
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320,
                    "examples": [
                      "+15555550123"
                    ]
                  },
                  "contact_id": {
                    "type": "string",
                    "pattern": "^ct_[0-9A-Za-z]{22}$",
                    "description": "A ct_ id.",
                    "examples": [
                      "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                    ]
                  },
                  "first_name": {
                    "description": "Saved on the contact when it has no first name yet.",
                    "type": "string",
                    "maxLength": 100
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "variables": {
                    "description": "Values for the steps’ `{{variables}}`.",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 500
                    }
                  }
                },
                "description": "A person to add to a sequence."
              },
              "example": {
                "to": "+15555550123",
                "first_name": "Maria",
                "variables": {
                  "listing": "412 Oak St"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Their run.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrollment"
                },
                "example": {
                  "id": "enr_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "enrollment",
                  "sequence_id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "handle": "+15555550123",
                  "state": "active",
                  "current_step": 0,
                  "next_run_at": "2026-11-13T19:41:00.000Z",
                  "stop_reason": null,
                  "enrolled_via": "api",
                  "variables": {
                    "listing": "412 Oak St"
                  },
                  "enrolled_at": "2026-11-13T19:41:00.000Z",
                  "completed_at": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "This person is already in that sequence.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listEnrollments",
        "summary": "List a sequence’s people",
        "description": "Everyone who was added to a sequence, newest first. `contact_id` narrows it to one person’s runs, to see whether they are in it now or were before.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The sequence’s id.",
            "schema": {
              "type": "string",
              "pattern": "^seq_[0-9A-Za-z]{22}$"
            },
            "example": "seq_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "name": "state",
            "in": "query",
            "required": false,
            "description": "Only runs in this state.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "completed",
                "stopped",
                "canceled"
              ]
            }
          },
          {
            "name": "contact_id",
            "in": "query",
            "required": false,
            "description": "Only this person’s runs.",
            "schema": {
              "type": "string",
              "pattern": "^ct_[0-9A-Za-z]{22}$",
              "examples": [
                "ct_1Hq2LxW9cVbN3mKpRtYs0a"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of runs.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Enrollment"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "enr_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "enrollment",
                      "sequence_id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                      "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                      "handle": "+15555550123",
                      "state": "active",
                      "current_step": 2,
                      "next_run_at": "2026-11-15T19:41:00.000Z",
                      "stop_reason": null,
                      "enrolled_via": "api",
                      "variables": {
                        "listing": "412 Oak St"
                      },
                      "enrolled_at": "2026-11-13T19:41:00.000Z",
                      "completed_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/enrollments/{id}": {
      "get": {
        "operationId": "getEnrollment",
        "summary": "Get a person’s run",
        "description": "One person’s run through a sequence, with a timeline of each text, wait and stop.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The run’s id.",
            "schema": {
              "type": "string",
              "pattern": "^enr_[0-9A-Za-z]{22}$"
            },
            "example": "enr_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The run, with its timeline.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrollment"
                },
                "example": {
                  "id": "enr_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "enrollment",
                  "sequence_id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "handle": "+15555550123",
                  "state": "active",
                  "current_step": 2,
                  "next_run_at": "2026-11-15T19:41:00.000Z",
                  "stop_reason": null,
                  "enrolled_via": "api",
                  "variables": {
                    "listing": "412 Oak St"
                  },
                  "enrolled_at": "2026-11-13T19:41:00.000Z",
                  "completed_at": null,
                  "timeline": [
                    {
                      "type": "enrolled",
                      "position": null,
                      "message_id": null,
                      "until": null,
                      "detail": "Added through the API.",
                      "at": "2026-11-13T19:41:00.000Z"
                    },
                    {
                      "type": "text_queued",
                      "position": 0,
                      "message_id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                      "until": null,
                      "detail": null,
                      "at": "2026-11-13T19:41:00.000Z"
                    },
                    {
                      "type": "waiting",
                      "position": 1,
                      "message_id": null,
                      "until": "2026-11-15T19:41:00.000Z",
                      "detail": "Waits 2 days.",
                      "at": "2026-11-13T19:41:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/enrollments/{id}/cancel": {
      "post": {
        "operationId": "cancelEnrollment",
        "summary": "Take a person out of a sequence",
        "description": "Ends this person’s run through the sequence. Its texts still waiting to go are canceled, and `sequence.completed` fires with `state: \"canceled\"`.",
        "tags": [
          "Sequences"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found",
          "conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The run’s id.",
            "schema": {
              "type": "string",
              "pattern": "^enr_[0-9A-Za-z]{22}$"
            },
            "example": "enr_1Hq2LxW9cVbN3mKpRtYs0a"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The run, ended.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Enrollment"
                },
                "example": {
                  "id": "enr_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "enrollment",
                  "sequence_id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "handle": "+15555550123",
                  "state": "canceled",
                  "current_step": 2,
                  "next_run_at": null,
                  "stop_reason": "canceled",
                  "enrolled_via": "api",
                  "variables": {
                    "listing": "412 Oak St"
                  },
                  "enrolled_at": "2026-11-13T19:41:00.000Z",
                  "completed_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`conflict`: Conflict.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "conflict": {
                    "summary": "Conflict",
                    "value": {
                      "error": {
                        "code": "conflict",
                        "message": "This enrollment already ended.",
                        "hint": "Read the current state and try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/hooks": {
      "post": {
        "operationId": "createTextHook",
        "summary": "Make a Text Hook",
        "description": "A Text Hook is an address any app can post to (Calendly, Typeform, Shopify, Stripe, Jotform, your own form) that turns the post into a text from your number. `mapping` says which posted field is the person’s number and what to say, with `{{body.…}}` for posted fields.\n\nAnyone with the address can send texts from your number, so keep it private. Start with `test_mode` on to check a real post without sending.",
        "tags": [
          "Text Hooks"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "limit_reached",
          "plan_lapsed",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "preset": {
                    "description": "Start from the usual fields of Calendly, Typeform, Shopify, Stripe or Jotform.",
                    "type": "string",
                    "enum": [
                      "calendly",
                      "typeform",
                      "shopify",
                      "stripe",
                      "jotform"
                    ]
                  },
                  "mapping": {
                    "type": "object",
                    "properties": {
                      "to": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "text": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "first_name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "last_name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "tags": {
                        "type": "string",
                        "maxLength": 200
                      }
                    }
                  },
                  "template_id": {
                    "type": "string",
                    "pattern": "^tpl_[0-9A-Za-z]{22}$",
                    "description": "A saved template to use instead of `text`."
                  },
                  "sequence_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^seq_[0-9A-Za-z]{22}$",
                        "description": "A seq_ id.",
                        "examples": [
                          "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "test_mode": {
                    "default": false,
                    "type": "boolean"
                  }
                },
                "required": [
                  "name"
                ],
                "description": "A Text Hook to make."
              },
              "example": {
                "name": "Calendly bookings",
                "preset": "calendly",
                "test_mode": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The Text Hook, with its address.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TextHook"
                },
                "example": {
                  "id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "text_hook",
                  "name": "Calendly bookings",
                  "url": "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHsQ2aVc0Ld",
                  "enabled": true,
                  "test_mode": true,
                  "mapping": {
                    "to": "{{body.payload.questions_and_answers.0.answer}}",
                    "text": "Hi {{body.payload.name}}, you’re booked for {{body.payload.scheduled_event.start_time}}. Text back if anything changes.",
                    "first_name": "{{body.payload.first_name}}",
                    "last_name": "{{body.payload.last_name}}",
                    "tags": "calendly"
                  },
                  "template_id": null,
                  "sequence_id": null,
                  "last_used_at": null,
                  "created_at": "2026-11-03T16:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listTextHooks",
        "summary": "List Text Hooks",
        "description": "Your Text Hooks, newest first.",
        "tags": [
          "Text Hooks"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of Text Hooks.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TextHook"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "text_hook",
                      "name": "Calendly bookings",
                      "url": "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHsQ2aVc0Ld",
                      "enabled": true,
                      "test_mode": false,
                      "mapping": {
                        "to": "{{body.payload.questions_and_answers.0.answer}}",
                        "text": "Hi {{body.payload.name}}, you’re booked for {{body.payload.scheduled_event.start_time}}. Text back if anything changes.",
                        "first_name": "{{body.payload.first_name}}",
                        "last_name": "{{body.payload.last_name}}",
                        "tags": "calendly"
                      },
                      "template_id": null,
                      "sequence_id": null,
                      "last_used_at": "2026-11-13T18:02:00.000Z",
                      "created_at": "2026-11-03T16:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/hooks/{id}": {
      "get": {
        "operationId": "getTextHook",
        "summary": "Get a Text Hook",
        "description": "One Text Hook with its address and mapping.",
        "tags": [
          "Text Hooks"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The Text Hook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^hook_[0-9A-Za-z]{22}$"
            },
            "example": "hook_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The Text Hook.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TextHook"
                },
                "example": {
                  "id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "text_hook",
                  "name": "Calendly bookings",
                  "url": "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHsQ2aVc0Ld",
                  "enabled": true,
                  "test_mode": false,
                  "mapping": {
                    "to": "{{body.payload.questions_and_answers.0.answer}}",
                    "text": "Hi {{body.payload.name}}, you’re booked for {{body.payload.scheduled_event.start_time}}. Text back if anything changes.",
                    "first_name": "{{body.payload.first_name}}",
                    "last_name": "{{body.payload.last_name}}",
                    "tags": "calendly"
                  },
                  "template_id": null,
                  "sequence_id": null,
                  "last_used_at": "2026-11-13T18:02:00.000Z",
                  "created_at": "2026-11-03T16:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateTextHook",
        "summary": "Change a Text Hook",
        "description": "Changes its name, mapping, words, sequence, or turns it or test mode on or off. Fields left out keep their values; within `mapping`, too.",
        "tags": [
          "Text Hooks"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The Text Hook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^hook_[0-9A-Za-z]{22}$"
            },
            "example": "hook_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "mapping": {
                    "type": "object",
                    "properties": {
                      "to": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "text": {
                        "type": "string",
                        "maxLength": 2000
                      },
                      "first_name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "last_name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "tags": {
                        "type": "string",
                        "maxLength": 200
                      }
                    }
                  },
                  "template_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^tpl_[0-9A-Za-z]{22}$",
                        "description": "A saved template to use instead of `text`."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "sequence_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^seq_[0-9A-Za-z]{22}$",
                        "description": "A seq_ id.",
                        "examples": [
                          "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "test_mode": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "test_mode": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed Text Hook.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TextHook"
                },
                "example": {
                  "id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "text_hook",
                  "name": "Calendly bookings",
                  "url": "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHsQ2aVc0Ld",
                  "enabled": true,
                  "test_mode": false,
                  "mapping": {
                    "to": "{{body.payload.questions_and_answers.0.answer}}",
                    "text": "Hi {{body.payload.name}}, you’re booked for {{body.payload.scheduled_event.start_time}}. Text back if anything changes.",
                    "first_name": "{{body.payload.first_name}}",
                    "last_name": "{{body.payload.last_name}}",
                    "tags": "calendly"
                  },
                  "template_id": null,
                  "sequence_id": null,
                  "last_used_at": "2026-11-13T18:02:00.000Z",
                  "created_at": "2026-11-03T16:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteTextHook",
        "summary": "Delete a Text Hook",
        "description": "Its address stops working at once, and its recent posts are deleted.",
        "tags": [
          "Text Hooks"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The Text Hook’s id.",
            "schema": {
              "type": "string",
              "pattern": "^hook_[0-9A-Za-z]{22}$"
            },
            "example": "hook_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "It is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "const": "text_hook"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ]
                },
                "example": {
                  "id": "hook_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "text_hook",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/automations/rules": {
      "get": {
        "operationId": "listKeywordRules",
        "summary": "List keyword rules",
        "description": "Your keyword rules, in the order they are tried. The first rule that matches a text wins.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, 1 to 100. Default 25.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The `next_cursor` of the page before. Leave it out for the first page.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of rules.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KeywordRule"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page follows."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Send as `cursor` for the next page; null on the last."
                    }
                  },
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ]
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                      "object": "keyword_rule",
                      "name": "Pricing",
                      "match": "word",
                      "keywords": [
                        "price",
                        "pricing",
                        "cost"
                      ],
                      "pattern": null,
                      "case_sensitive": false,
                      "actions": [
                        {
                          "type": "reply",
                          "text": "Our plans start at $29 a month. Want me to send the details?",
                          "template_id": null
                        },
                        {
                          "type": "tag",
                          "tags": [
                            "asked-pricing"
                          ]
                        }
                      ],
                      "position": 10,
                      "enabled": true,
                      "fire_count": 18,
                      "last_fired_at": "2026-11-13T17:20:00.000Z",
                      "created_at": "2026-11-02T15:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createKeywordRule",
        "summary": "Make a keyword rule",
        "description": "When an incoming one-to-one text matches, the rule replies with words or a template, tags the person, adds them to a sequence, or sends an `automation.matched` webhook event, in the order you list them. Only the first matching rule runs.\n\n`match` is `exact` (the whole text is the keyword, ignoring case and punctuation at the ends), `starts_with`, `word` (the keyword as a whole word anywhere), `contains`, or `regex`. A stop word never matches: it stops the person and nothing else.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found",
          "limit_reached",
          "plan_lapsed",
          "idempotency_conflict"
        ],
        "x-idempotent": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "match": {
                    "type": "string",
                    "enum": [
                      "exact",
                      "starts_with",
                      "word",
                      "contains",
                      "regex"
                    ]
                  },
                  "keywords": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    }
                  },
                  "pattern": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "case_sensitive": {
                    "type": "boolean"
                  },
                  "actions": {
                    "minItems": 1,
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "reply"
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2000,
                              "description": "The reply, with `{{variables}}`."
                            },
                            "template_id": {
                              "type": "string",
                              "pattern": "^tpl_[0-9A-Za-z]{22}$",
                              "description": "A saved template to use instead of `text`."
                            }
                          },
                          "required": [
                            "type"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "tag"
                            },
                            "tags": {
                              "minItems": 1,
                              "maxItems": 10,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 40
                              }
                            }
                          },
                          "required": [
                            "type",
                            "tags"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "enroll"
                            },
                            "sequence_id": {
                              "type": "string",
                              "pattern": "^seq_[0-9A-Za-z]{22}$",
                              "description": "A seq_ id.",
                              "examples": [
                                "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "sequence_id"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "webhook"
                            }
                          },
                          "required": [
                            "type"
                          ]
                        }
                      ]
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "position": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  }
                },
                "required": [
                  "name",
                  "match",
                  "actions"
                ],
                "description": "A keyword rule to make."
              },
              "example": {
                "name": "Pricing",
                "match": "word",
                "keywords": [
                  "price",
                  "pricing",
                  "cost"
                ],
                "actions": [
                  {
                    "type": "reply",
                    "text": "Our plans start at $29 a month. Want me to send the details?"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The rule.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordRule"
                },
                "example": {
                  "id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "keyword_rule",
                  "name": "Pricing",
                  "match": "word",
                  "keywords": [
                    "price",
                    "pricing",
                    "cost"
                  ],
                  "pattern": null,
                  "case_sensitive": false,
                  "actions": [
                    {
                      "type": "reply",
                      "text": "Our plans start at $29 a month. Want me to send the details?",
                      "template_id": null
                    },
                    {
                      "type": "tag",
                      "tags": [
                        "asked-pricing"
                      ]
                    }
                  ],
                  "position": 10,
                  "enabled": true,
                  "fire_count": 0,
                  "last_fired_at": null,
                  "created_at": "2026-11-02T15:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "`plan_lapsed`: Plan lapsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "plan_lapsed": {
                    "summary": "Plan lapsed",
                    "value": {
                      "error": {
                        "code": "plan_lapsed",
                        "message": "Your plan isn’t active. Update your card on the Billing page.",
                        "hint": "Update the card on the Billing page; texts wait until the plan is active.",
                        "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "`limit_reached`: Limit reached. `idempotency_conflict`: Idempotency key reused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "limit_reached": {
                    "summary": "Limit reached",
                    "value": {
                      "error": {
                        "code": "limit_reached",
                        "message": "You already have 10 API keys. Revoke one to make another.",
                        "hint": "You have reached a limit on your account. The docs list each limit.",
                        "doc_url": "https://usebluebot.com/docs/errors/limit_reached",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  },
                  "idempotency_conflict": {
                    "summary": "Idempotency key reused",
                    "value": {
                      "error": {
                        "code": "idempotency_conflict",
                        "message": "This Idempotency-Key was used with a different request.",
                        "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
                        "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/automations/rules/{id}": {
      "get": {
        "operationId": "getKeywordRule",
        "summary": "Get a keyword rule",
        "description": "One keyword rule, with what it matches and does.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The rule’s id.",
            "schema": {
              "type": "string",
              "pattern": "^kw_[0-9A-Za-z]{22}$"
            },
            "example": "kw_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "The rule.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordRule"
                },
                "example": {
                  "id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "keyword_rule",
                  "name": "Pricing",
                  "match": "word",
                  "keywords": [
                    "price",
                    "pricing",
                    "cost"
                  ],
                  "pattern": null,
                  "case_sensitive": false,
                  "actions": [
                    {
                      "type": "reply",
                      "text": "Our plans start at $29 a month. Want me to send the details?",
                      "template_id": null
                    },
                    {
                      "type": "tag",
                      "tags": [
                        "asked-pricing"
                      ]
                    }
                  ],
                  "position": 10,
                  "enabled": true,
                  "fire_count": 18,
                  "last_fired_at": "2026-11-13T17:20:00.000Z",
                  "created_at": "2026-11-02T15:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateKeywordRule",
        "summary": "Change a keyword rule",
        "description": "Changes what it matches, what it does, its position, or turns it off.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The rule’s id.",
            "schema": {
              "type": "string",
              "pattern": "^kw_[0-9A-Za-z]{22}$"
            },
            "example": "kw_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "match": {
                    "type": "string",
                    "enum": [
                      "exact",
                      "starts_with",
                      "word",
                      "contains",
                      "regex"
                    ]
                  },
                  "keywords": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 100
                    }
                  },
                  "pattern": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "case_sensitive": {
                    "type": "boolean"
                  },
                  "actions": {
                    "minItems": 1,
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "reply"
                            },
                            "text": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2000,
                              "description": "The reply, with `{{variables}}`."
                            },
                            "template_id": {
                              "type": "string",
                              "pattern": "^tpl_[0-9A-Za-z]{22}$",
                              "description": "A saved template to use instead of `text`."
                            }
                          },
                          "required": [
                            "type"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "tag"
                            },
                            "tags": {
                              "minItems": 1,
                              "maxItems": 10,
                              "type": "array",
                              "items": {
                                "type": "string",
                                "minLength": 1,
                                "maxLength": 40
                              }
                            }
                          },
                          "required": [
                            "type",
                            "tags"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "enroll"
                            },
                            "sequence_id": {
                              "type": "string",
                              "pattern": "^seq_[0-9A-Za-z]{22}$",
                              "description": "A seq_ id.",
                              "examples": [
                                "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                              ]
                            }
                          },
                          "required": [
                            "type",
                            "sequence_id"
                          ]
                        },
                        {
                          "type": "object",
                          "properties": {
                            "type": {
                              "type": "string",
                              "const": "webhook"
                            }
                          },
                          "required": [
                            "type"
                          ]
                        }
                      ]
                    }
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "position": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10000
                  }
                }
              },
              "example": {
                "enabled": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The changed rule.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordRule"
                },
                "example": {
                  "id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "keyword_rule",
                  "name": "Pricing",
                  "match": "word",
                  "keywords": [
                    "price",
                    "pricing",
                    "cost"
                  ],
                  "pattern": null,
                  "case_sensitive": false,
                  "actions": [
                    {
                      "type": "reply",
                      "text": "Our plans start at $29 a month. Want me to send the details?",
                      "template_id": null
                    },
                    {
                      "type": "tag",
                      "tags": [
                        "asked-pricing"
                      ]
                    }
                  ],
                  "position": 10,
                  "enabled": false,
                  "fire_count": 18,
                  "last_fired_at": "2026-11-13T17:20:00.000Z",
                  "created_at": "2026-11-02T15:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteKeywordRule",
        "summary": "Delete a keyword rule",
        "description": "The rule stops matching at once.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "not_found"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The rule’s id.",
            "schema": {
              "type": "string",
              "pattern": "^kw_[0-9A-Za-z]{22}$"
            },
            "example": "kw_1Hq2LxW9cVbN3mKpRtYs0a"
          }
        ],
        "responses": {
          "200": {
            "description": "It is gone.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "const": "keyword_rule"
                    },
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "id",
                    "object",
                    "deleted"
                  ]
                },
                "example": {
                  "id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "keyword_rule",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found`: Not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "not_found": {
                    "summary": "Not found",
                    "value": {
                      "error": {
                        "code": "not_found",
                        "message": "There’s no message with that id.",
                        "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
                        "doc_url": "https://usebluebot.com/docs/errors/not_found",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/automations/away": {
      "get": {
        "operationId": "getAwayMessage",
        "summary": "Get the away message",
        "description": "The reply sent outside your business hours, and the hours.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:read",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "The away message.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AwayMessage"
                },
                "example": {
                  "object": "away_message",
                  "enabled": true,
                  "text": "Thanks for your text! We’re closed right now and will reply when we open at 9 AM.",
                  "cooldown_hours": 12,
                  "business_hours": {
                    "mon": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "tue": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "wed": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "thu": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "fri": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "sat": null,
                    "sun": null
                  },
                  "time_zone": "America/Chicago",
                  "open_now": true
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateAwayMessage",
        "summary": "Change the away message",
        "description": "Turns it on or off, or changes its words, your hours or how often one person can get it. It goes to a one-to-one text that arrives outside your hours when no keyword rule replied, at most once per person per `cooldown_hours`.",
        "tags": [
          "Automations"
        ],
        "x-scope": "messages:send",
        "x-error-codes": [
          "unauthorized",
          "insufficient_scope",
          "rate_limited",
          "internal",
          "invalid_request"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000,
                    "description": "The reply, with `{{variables}}`."
                  },
                  "cooldown_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 168
                  },
                  "business_hours": {
                    "type": "object",
                    "properties": {
                      "mon": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "tue": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "wed": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "thu": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "fri": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "sat": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "sun": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "start": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              },
                              "end": {
                                "type": "string",
                                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                                "description": "A time of day as HH:MM in your account’s time zone."
                              }
                            },
                            "required": [
                              "start",
                              "end"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "mon",
                      "tue",
                      "wed",
                      "thu",
                      "fri",
                      "sat",
                      "sun"
                    ],
                    "description": "Your hours each day in your time zone; null for a day you’re closed."
                  }
                }
              },
              "example": {
                "enabled": true,
                "cooldown_hours": 12
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The away message.",
            "headers": {
              "Request-Id": {
                "$ref": "#/components/headers/Request-Id"
              },
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimit-Limit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimit-Remaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimit-Reset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AwayMessage"
                },
                "example": {
                  "object": "away_message",
                  "enabled": true,
                  "text": "Thanks for your text! We’re closed right now and will reply when we open at 9 AM.",
                  "cooldown_hours": 12,
                  "business_hours": {
                    "mon": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "tue": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "wed": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "thu": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "fri": {
                      "start": "09:00",
                      "end": "17:00"
                    },
                    "sat": null,
                    "sun": null
                  },
                  "time_zone": "America/Chicago",
                  "open_now": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`: Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "invalid_request": {
                    "summary": "Invalid request",
                    "value": {
                      "error": {
                        "code": "invalid_request",
                        "message": "Send `to` or `chat_id`.",
                        "hint": "Check the fields named in the message and send it again.",
                        "doc_url": "https://usebluebot.com/docs/errors/invalid_request",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized`: Unauthorized.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "unauthorized": {
                    "summary": "Unauthorized",
                    "value": {
                      "error": {
                        "code": "unauthorized",
                        "message": "That API key isn’t valid. Check it on the API keys page.",
                        "hint": "Send a valid key as `Authorization: Bearer <key>`.",
                        "doc_url": "https://usebluebot.com/docs/errors/unauthorized",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`: Insufficient scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "insufficient_scope": {
                    "summary": "Insufficient scope",
                    "value": {
                      "error": {
                        "code": "insufficient_scope",
                        "message": "This key doesn’t have the `messages:send` scope.",
                        "hint": "Make a key with the scope named in the message.",
                        "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited`: Rate limited.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/Retry-After"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "rate_limited": {
                    "summary": "Rate limited",
                    "value": {
                      "error": {
                        "code": "rate_limited",
                        "message": "Too many requests. Wait 12 seconds.",
                        "hint": "Wait the number of seconds in `retry_after`, then try again.",
                        "doc_url": "https://usebluebot.com/docs/errors/rate_limited",
                        "retry_after": 12,
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`internal`: Internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "examples": {
                  "internal": {
                    "summary": "Internal error",
                    "value": {
                      "error": {
                        "code": "internal",
                        "message": "Something went wrong on our side.",
                        "hint": "Try again. If it keeps happening, write to support with the request_id.",
                        "doc_url": "https://usebluebot.com/docs/errors/internal",
                        "request_id": "req_1Hq2LxW9cVbN3mKpRtYs0a"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "message.queued": {
      "post": {
        "operationId": "event_message_queued",
        "summary": "Message queued",
        "description": "A text was accepted and is waiting for the Mac, or a scheduled text became due.\n\nIts `hold` says why it is waiting, if anything holds it. A queued text can still be canceled.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.queued"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.queued",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "queued",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.sent": {
      "post": {
        "operationId": "event_message_sent",
        "summary": "Message sent",
        "description": "Messages on the Mac showed the text sent. Also fires for a text you typed by hand on your Mac or iPhone, with `source: \"mac\"`.\n\n`service` says whether it went as an iMessage or a regular text. A text sent with a file that couldn’t be attached is sent with `failure` set.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.sent"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.sent",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "sent",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": "2026-11-13T19:41:05.000Z",
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.delivered": {
      "post": {
        "operationId": "event_message_delivered",
        "summary": "Message delivered",
        "description": "iMessage showed the text delivered to the person’s device.\n\nRegular texts (SMS) never report delivery, so a text that went as SMS stays `sent`.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.delivered"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.delivered",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "delivered",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": "2026-11-13T19:41:05.000Z",
                  "delivered_at": "2026-11-13T19:41:06.000Z",
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.read": {
      "post": {
        "operationId": "event_message_read",
        "summary": "Message read",
        "description": "The person read the text. Only for people who share read receipts.\n\nMost people don’t share read receipts, so don’t wait for this event.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.read"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.read",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "read",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": "2026-11-13T19:41:05.000Z",
                  "delivered_at": "2026-11-13T19:41:06.000Z",
                  "read_at": "2026-11-13T19:43:30.000Z",
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.failed": {
      "post": {
        "operationId": "event_message_failed",
        "summary": "Message failed",
        "description": "Messages couldn’t send the text, or it was an iMessage-only text to somebody not on iMessage.\n\n`failure.reason` is a stable code and `failure.detail` says what the Mac saw.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.failed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.failed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "failed",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "imessage",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": {
                    "reason": "not_on_imessage",
                    "detail": "Messages couldn’t send this as an iMessage."
                  },
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": "2026-11-13T19:41:09.000Z",
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.unconfirmed": {
      "post": {
        "operationId": "event_message_unconfirmed",
        "summary": "Message unconfirmed",
        "description": "The Mac took the text and didn’t say whether it went before its 3-minute lease ran out.\n\nIt may have gone. Check the conversation, then settle it with `POST /v1/messages/{id}/resolve`: `mark_sent` if it went, `send_again` if not. BlueBot never sends it again on its own.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.unconfirmed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.unconfirmed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "unconfirmed",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": "2026-11-13T19:41:02.000Z",
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": "2026-11-13T19:44:02.000Z",
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.expired": {
      "post": {
        "operationId": "event_message_expired",
        "summary": "Message expired",
        "description": "The text was still waiting when its `expires_at` passed, so it will never go.\n\nUsually the Mac was away or the text sat behind quiet hours or a daily limit for longer than the expiry setting.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.expired"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.expired",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "expired",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": "2026-11-14T19:41:00.000Z",
                  "canceled_at": null,
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.canceled": {
      "post": {
        "operationId": "event_message_canceled",
        "summary": "Message canceled",
        "description": "A queued or scheduled text was canceled: by you, because the person is on your stop list, or when its sequence or broadcast stopped.\n\n`cancel_reason` says which.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.canceled"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.canceled",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "message",
                  "direction": "out",
                  "state": "canceled",
                  "to": "+15555550123",
                  "from": "+15555550100",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM.",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": null,
                  "sms_retry": false,
                  "source": "api",
                  "source_ref": null,
                  "metadata": {
                    "crm_id": "48213"
                  },
                  "hold": null,
                  "send_at": null,
                  "expires_at": "2026-11-14T19:41:00.000Z",
                  "failure": null,
                  "cancel_reason": "opted_out",
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:41:00.000Z",
                  "queued_at": "2026-11-13T19:41:00.000Z",
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": "2026-11-13T19:42:00.000Z",
                  "received_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.received": {
      "post": {
        "operationId": "event_message_received",
        "summary": "Message received",
        "description": "Somebody texted you. Pictures and voice memos are on the message as files.\n\nFires once the Mac has uploaded the message’s files, or after 2 minutes without them (their `status` is then `waiting`). Group texts carry `chat_id`.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.received"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.received",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                  "object": "message",
                  "direction": "in",
                  "state": "received",
                  "to": "+15555550100",
                  "from": "+15555550123",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Perfect, see you there!",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "mac",
                  "source_ref": null,
                  "metadata": {},
                  "hold": null,
                  "send_at": null,
                  "expires_at": null,
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:44:12.000Z",
                  "queued_at": null,
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": "2026-11-13T19:44:10.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.edited": {
      "post": {
        "operationId": "event_message_edited",
        "summary": "Message edited",
        "description": "A text was edited in Messages, by you or by the other person.\n\n`text` is the new words and `edited_at` when. BlueBot can read edits but can’t make them.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.edited"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.edited",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                  "object": "message",
                  "direction": "in",
                  "state": "received",
                  "to": "+15555550100",
                  "from": "+15555550123",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": "Perfect, see you there at 3!",
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "mac",
                  "source_ref": null,
                  "metadata": {},
                  "hold": null,
                  "send_at": null,
                  "expires_at": null,
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": "2026-11-13T19:44:40.000Z",
                  "unsent_at": null,
                  "created_at": "2026-11-13T19:44:12.000Z",
                  "queued_at": null,
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": "2026-11-13T19:44:10.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "message.unsent": {
      "post": {
        "operationId": "event_message_unsent",
        "summary": "Message unsent",
        "description": "A text was unsent in Messages. Its words are gone from BlueBot too.\n\n`text` is null and `unsent_at` says when.",
        "tags": [
          "Events"
        ],
        "x-event-group": "messages",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "message.unsent"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Message"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "message.unsent",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                  "object": "message",
                  "direction": "in",
                  "state": "received",
                  "to": "+15555550100",
                  "from": "+15555550123",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "text": null,
                  "text_deleted": false,
                  "files": [],
                  "service_requested": "auto",
                  "service": "imessage",
                  "sms_retry": false,
                  "source": "mac",
                  "source_ref": null,
                  "metadata": {},
                  "hold": null,
                  "send_at": null,
                  "expires_at": null,
                  "failure": null,
                  "cancel_reason": null,
                  "resolution": null,
                  "resolved_at": null,
                  "resent_message_id": null,
                  "reply_to_id": null,
                  "reactions": [],
                  "edited_at": null,
                  "unsent_at": "2026-11-13T19:45:00.000Z",
                  "created_at": "2026-11-13T19:44:12.000Z",
                  "queued_at": null,
                  "sending_at": null,
                  "sent_at": null,
                  "delivered_at": null,
                  "read_at": null,
                  "failed_at": null,
                  "unconfirmed_at": null,
                  "expired_at": null,
                  "canceled_at": null,
                  "received_at": "2026-11-13T19:44:10.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "reaction.added": {
      "post": {
        "operationId": "event_reaction_added",
        "summary": "Reaction added",
        "description": "Somebody added a tapback (love, like, laugh and so on) to a text, or you did from your Mac or iPhone.\n\n`direction` says whose it was. BlueBot can read tapbacks but can’t send them.",
        "tags": [
          "Events"
        ],
        "x-event-group": "reactions",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "reaction.added"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/ReactionEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "reaction.added",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "rxn_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "reaction",
                  "kind": "love",
                  "emoji": null,
                  "from": "+15555550123",
                  "direction": "in",
                  "added_at": "2026-11-13T19:45:00.000Z",
                  "message_id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "removed_at": null
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "reaction.removed": {
      "post": {
        "operationId": "event_reaction_removed",
        "summary": "Reaction removed",
        "description": "A tapback was taken back.\n\nThe reaction has the id `reaction.added` gave it.",
        "tags": [
          "Events"
        ],
        "x-event-group": "reactions",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "reaction.removed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/ReactionEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "reaction.removed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "rxn_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "reaction",
                  "kind": "love",
                  "emoji": null,
                  "from": "+15555550123",
                  "direction": "in",
                  "added_at": "2026-11-13T19:45:00.000Z",
                  "message_id": "msg_1Hq2LxW9cVbN3mKpRtYs0a",
                  "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                  "chat_id": null,
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "removed_at": "2026-11-13T19:46:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "chat.created": {
      "post": {
        "operationId": "event_chat_created",
        "summary": "Chat created",
        "description": "The Mac saw a chat BlueBot didn’t know: a new group, or a first text with somebody.\n\nA group chat’s id is what `chat_id` takes on a send.",
        "tags": [
          "Events"
        ],
        "x-event-group": "chats",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "chat.created"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Chat"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "chat.created",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "chat_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "chat",
                  "name": "Oak St closing",
                  "is_group": true,
                  "participants": [
                    "+15555550123",
                    "+15555550187"
                  ],
                  "service": "imessage",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "contact.created": {
      "post": {
        "operationId": "event_contact_created",
        "summary": "Contact created",
        "description": "A person was added: by a send to somebody new, a text from somebody new, an import, the API or the dashboard.\n\n`created_via` says how.",
        "tags": [
          "Events"
        ],
        "x-event-group": "contacts",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "contact.created"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Contact"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "contact.created",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer"
                  ],
                  "custom_fields": {},
                  "stopped": false,
                  "stopped_at": null,
                  "stop_source": null,
                  "last_service": "imessage",
                  "first_message_at": null,
                  "last_message_at": null,
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "contact.stopped": {
      "post": {
        "operationId": "event_contact_stopped",
        "summary": "Contact stopped",
        "description": "A person went on your stop list. Their queued texts were canceled.\n\n`stop_source: \"reply\"` means they texted a stop word such as STOP. BlueBot won’t text them again until they text START or you take them off the list.",
        "tags": [
          "Events"
        ],
        "x-event-group": "contacts",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "contact.stopped"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Contact"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "contact.stopped",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer"
                  ],
                  "custom_fields": {},
                  "stopped": true,
                  "stopped_at": "2026-11-13T19:50:00.000Z",
                  "stop_source": "reply",
                  "last_service": "imessage",
                  "first_message_at": "2026-11-13T19:41:00.000Z",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "contact.unstopped": {
      "post": {
        "operationId": "event_contact_unstopped",
        "summary": "Contact unstopped",
        "description": "A person came off your stop list: they texted START, or you took them off.\n\nTexts to them go again from now on. Texts canceled while they were stopped stay canceled.",
        "tags": [
          "Events"
        ],
        "x-event-group": "contacts",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "contact.unstopped"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/Contact"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "contact.unstopped",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "contact",
                  "handle": "+15555550123",
                  "kind": "phone",
                  "first_name": "Maria",
                  "last_name": "Alvarez",
                  "company": null,
                  "tags": [
                    "buyer"
                  ],
                  "custom_fields": {},
                  "stopped": false,
                  "stopped_at": null,
                  "stop_source": null,
                  "last_service": "imessage",
                  "first_message_at": "2026-11-13T19:41:00.000Z",
                  "last_message_at": "2026-11-13T19:41:00.000Z",
                  "created_via": "api",
                  "created_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "sequence.completed": {
      "post": {
        "operationId": "event_sequence_completed",
        "summary": "Sequence completed",
        "description": "A person reached the end of a sequence, or it stopped early because they replied or stopped.\n\n`state` and `stop_reason` say which.",
        "tags": [
          "Events"
        ],
        "x-event-group": "automations",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "sequence.completed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/EnrollmentEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "sequence.completed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "enr_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "enrollment",
                  "sequence_id": "seq_1Hq2LxW9cVbN3mKpRtYs0a",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "handle": "+15555550123",
                  "contact": {
                    "id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                    "object": "contact",
                    "handle": "+15555550123",
                    "kind": "phone",
                    "first_name": "Maria",
                    "last_name": "Alvarez",
                    "company": null,
                    "tags": [
                      "buyer"
                    ],
                    "custom_fields": {},
                    "stopped": false,
                    "stopped_at": null,
                    "stop_source": null,
                    "last_service": "imessage",
                    "first_message_at": "2026-11-13T19:41:00.000Z",
                    "last_message_at": "2026-11-13T19:41:00.000Z",
                    "created_via": "api",
                    "created_at": "2026-11-13T19:41:00.000Z"
                  },
                  "state": "stopped",
                  "stop_reason": "replied",
                  "completed_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "broadcast.completed": {
      "post": {
        "operationId": "event_broadcast_completed",
        "summary": "Broadcast completed",
        "description": "Every text in a broadcast has settled: sent, failed, skipped, expired or canceled.\n\n`counts` has the totals.",
        "tags": [
          "Events"
        ],
        "x-event-group": "automations",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "broadcast.completed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/BroadcastEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "broadcast.completed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "bc_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "broadcast",
                  "name": "Open house Saturday",
                  "state": "completed",
                  "recipient_count": 42,
                  "counts": {
                    "sent": 12,
                    "delivered": 27,
                    "failed": 1,
                    "skipped": 2
                  },
                  "completed_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "automation.matched": {
      "post": {
        "operationId": "event_automation_matched",
        "summary": "Keyword rule matched",
        "description": "An incoming text matched a keyword rule that has the “Send a webhook event” action.\n\nFires once per incoming text, for the first rule that matched. `message` is the text that matched. A stop word never matches a rule, so it never fires for one.",
        "tags": [
          "Events"
        ],
        "x-event-group": "automations",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "automation.matched"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/AutomationMatch"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "automation.matched",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "object": "automation_match",
                  "rule_id": "kw_1Hq2LxW9cVbN3mKpRtYs0a",
                  "rule_name": "Pricing",
                  "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                  "actions": [
                    "reply",
                    "tag",
                    "webhook"
                  ],
                  "message": {
                    "id": "msg_2Bf8QzD4kJmA6nXwEuTr1c",
                    "object": "message",
                    "direction": "in",
                    "state": "received",
                    "to": "+15555550100",
                    "from": "+15555550123",
                    "chat_id": null,
                    "contact_id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
                    "conversation_id": "conv_1Hq2LxW9cVbN3mKpRtYs0a",
                    "text": "PRICING",
                    "text_deleted": false,
                    "files": [],
                    "service_requested": "auto",
                    "service": "imessage",
                    "sms_retry": false,
                    "source": "mac",
                    "source_ref": null,
                    "metadata": {},
                    "hold": null,
                    "send_at": null,
                    "expires_at": null,
                    "failure": null,
                    "cancel_reason": null,
                    "resolution": null,
                    "resolved_at": null,
                    "resent_message_id": null,
                    "reply_to_id": null,
                    "reactions": [],
                    "edited_at": null,
                    "unsent_at": null,
                    "created_at": "2026-11-13T19:44:12.000Z",
                    "queued_at": null,
                    "sending_at": null,
                    "sent_at": null,
                    "delivered_at": null,
                    "read_at": null,
                    "failed_at": null,
                    "unconfirmed_at": null,
                    "expired_at": null,
                    "canceled_at": null,
                    "received_at": "2026-11-13T19:44:10.000Z"
                  },
                  "matched_at": "2026-11-13T19:41:00.000Z"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "device.online": {
      "post": {
        "operationId": "event_device_online",
        "summary": "Mac online",
        "description": "The Mac checked in after being offline. Held texts start going.\n\nAlso fires the first time a newly connected Mac checks in.",
        "tags": [
          "Events"
        ],
        "x-event-group": "device",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "device.online"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/DeviceEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "device.online",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "dev_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "device",
                  "status": "online",
                  "name": "Dana’s MacBook Air",
                  "number": "+15555550100",
                  "app_version": "1.0.0",
                  "macos_version": "15.1",
                  "last_seen_at": "2026-11-13T19:41:00.000Z",
                  "last_sync_at": "2026-11-13T19:41:00.000Z",
                  "offline_since": null,
                  "paired_at": "2026-11-01T15:00:00.000Z",
                  "checks": {
                    "messages": {
                      "state": "ok",
                      "detail": null
                    },
                    "full_disk_access": {
                      "state": "ok",
                      "detail": null
                    },
                    "forwarding": {
                      "state": "ok",
                      "detail": null
                    },
                    "awake": {
                      "state": "ok",
                      "detail": null
                    },
                    "filevault": {
                      "state": "ok",
                      "detail": null
                    }
                  },
                  "checks_ok": true,
                  "transcription": false,
                  "held_count": 0,
                  "queued_count": 0,
                  "unconfirmed_count": 0,
                  "paused_until": null,
                  "today": {
                    "sent": 14,
                    "new_people": 3,
                    "new_people_limit": 50,
                    "daily_limit": 1000,
                    "resets_at": "2026-11-14T05:00:00.000Z"
                  },
                  "failed_checks": []
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "device.offline": {
      "post": {
        "operationId": "event_device_offline",
        "summary": "Mac offline",
        "description": "The Mac hasn’t checked in for 2 minutes. Texts wait with `hold.reason: \"device_offline\"`.\n\nThe owner is emailed once if it stays away 10 minutes.",
        "tags": [
          "Events"
        ],
        "x-event-group": "device",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "device.offline"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/DeviceEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "device.offline",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "dev_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "device",
                  "status": "offline",
                  "name": "Dana’s MacBook Air",
                  "number": "+15555550100",
                  "app_version": "1.0.0",
                  "macos_version": "15.1",
                  "last_seen_at": "2026-11-13T19:41:00.000Z",
                  "last_sync_at": "2026-11-13T19:41:00.000Z",
                  "offline_since": "2026-11-13T19:39:00.000Z",
                  "paired_at": "2026-11-01T15:00:00.000Z",
                  "checks": {
                    "messages": {
                      "state": "ok",
                      "detail": null
                    },
                    "full_disk_access": {
                      "state": "ok",
                      "detail": null
                    },
                    "forwarding": {
                      "state": "ok",
                      "detail": null
                    },
                    "awake": {
                      "state": "ok",
                      "detail": null
                    },
                    "filevault": {
                      "state": "ok",
                      "detail": null
                    }
                  },
                  "checks_ok": true,
                  "transcription": false,
                  "held_count": 2,
                  "queued_count": 2,
                  "unconfirmed_count": 0,
                  "paused_until": null,
                  "today": {
                    "sent": 14,
                    "new_people": 3,
                    "new_people_limit": 50,
                    "daily_limit": 1000,
                    "resets_at": "2026-11-14T05:00:00.000Z"
                  },
                  "failed_checks": []
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    },
    "device.check_failed": {
      "post": {
        "operationId": "event_device_check_failed",
        "summary": "Mac check failed",
        "description": "One of the Mac’s setup checks turned `needs_you`, such as Messages signing out or Full Disk Access being turned off.\n\n`failed_checks` names them and each check’s `detail` says what the Mac saw.",
        "tags": [
          "Events"
        ],
        "x-event-group": "device",
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event id, the same on every retry.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "Seconds since 1970 when this try was signed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and the base64 HMAC-SHA256 of `{webhook-id}.{webhook-timestamp}.{body}`. During a secret rotation two signatures, separated by a space.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event id."
                  },
                  "object": {
                    "type": "string",
                    "const": "event"
                  },
                  "type": {
                    "type": "string",
                    "const": "device.check_failed"
                  },
                  "api_version": {
                    "type": "string",
                    "description": "The webhook’s pinned payload version."
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "data": {
                    "$ref": "#/components/schemas/DeviceEvent"
                  }
                },
                "required": [
                  "id",
                  "object",
                  "type",
                  "api_version",
                  "timestamp",
                  "data"
                ]
              },
              "example": {
                "id": "evt_1Hq2LxW9cVbN3mKpRtYs0a",
                "object": "event",
                "type": "device.check_failed",
                "api_version": "2026-11-13",
                "timestamp": "2026-11-13T19:41:00.000Z",
                "data": {
                  "id": "dev_1Hq2LxW9cVbN3mKpRtYs0a",
                  "object": "device",
                  "status": "online",
                  "name": "Dana’s MacBook Air",
                  "number": "+15555550100",
                  "app_version": "1.0.0",
                  "macos_version": "15.1",
                  "last_seen_at": "2026-11-13T19:41:00.000Z",
                  "last_sync_at": "2026-11-13T19:41:00.000Z",
                  "offline_since": null,
                  "paired_at": "2026-11-01T15:00:00.000Z",
                  "checks": {
                    "messages": {
                      "state": "needs_you",
                      "detail": "Messages isn’t signed in to iMessage."
                    },
                    "full_disk_access": {
                      "state": "ok",
                      "detail": null
                    },
                    "forwarding": {
                      "state": "ok",
                      "detail": null
                    },
                    "awake": {
                      "state": "ok",
                      "detail": null
                    },
                    "filevault": {
                      "state": "ok",
                      "detail": null
                    }
                  },
                  "checks_ok": false,
                  "transcription": false,
                  "held_count": 0,
                  "queued_count": 0,
                  "unconfirmed_count": 0,
                  "paused_until": null,
                  "today": {
                    "sent": 14,
                    "new_people": 3,
                    "new_people_limit": 50,
                    "daily_limit": 1000,
                    "resets_at": "2026-11-14T05:00:00.000Z"
                  },
                  "failed_checks": [
                    "messages"
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Deletes the webhook. Nothing more is sent to it."
          },
          "2XX": {
            "description": "Received. Answer within 10 seconds; do the work afterwards."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key: `bb_live_…`, or `bb_test_…` off production."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "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`.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      }
    },
    "headers": {
      "Request-Id": {
        "description": "This request’s id. Quote it when writing to support.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimit-Limit": {
        "description": "Requests a key may make a minute (120).",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Remaining": {
        "description": "Requests left this minute.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Seconds until the minute starts again.",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before trying again.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "schemas": {
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^msg_[0-9A-Za-z]{22}$",
            "description": "A msg_ id.",
            "examples": [
              "msg_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "message"
          },
          "direction": {
            "type": "string",
            "enum": [
              "out",
              "in"
            ],
            "description": "`out` for a text from your number, `in` for one to it."
          },
          "state": {
            "type": "string",
            "enum": [
              "scheduled",
              "queued",
              "sending",
              "sent",
              "delivered",
              "read",
              "failed",
              "unconfirmed",
              "expired",
              "canceled",
              "received"
            ],
            "description": "Out: `scheduled`, `queued`, `sending`, `sent`, `delivered`, `read`, `failed`, `unconfirmed`, `expired`, `canceled`. In: `received`."
          },
          "to": {
            "anyOf": [
              {
                "type": "string",
                "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
                "examples": [
                  "+15555550123"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who it went to. For a text in, your own number when the Mac knows it. Null in a group chat."
          },
          "from": {
            "anyOf": [
              {
                "type": "string",
                "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
                "examples": [
                  "+15555550123"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who sent it. For a text out, your own number when the Mac knows it."
          },
          "chat_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^chat_[0-9A-Za-z]{22}$",
                "description": "A chat_ id.",
                "examples": [
                  "chat_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The group chat it is in; null for a one-to-one text."
          },
          "contact_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^ct_[0-9A-Za-z]{22}$",
                "description": "A ct_ id.",
                "examples": [
                  "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The person, or for a group text in, the member who sent it."
          },
          "conversation_id": {
            "type": "string",
            "pattern": "^conv_[0-9A-Za-z]{22}$",
            "description": "A conv_ id.",
            "examples": [
              "conv_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "text": {
            "description": "The words. Null for a files-only text, an unsent one, and after 30 days, when BlueBot deletes the words and keeps the facts.",
            "examples": [
              "Hi Maria, the showing at 412 Oak St is confirmed for 3 PM."
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "text_deleted": {
            "type": "boolean",
            "description": "True once the words were deleted after 30 days."
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/File"
            },
            "description": "Pictures and files on the text, in order."
          },
          "service_requested": {
            "type": "string",
            "enum": [
              "auto",
              "imessage",
              "sms"
            ],
            "description": "What the caller asked for. `auto` uses the service of the newest chat with the person, else iMessage."
          },
          "service": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "imessage",
                  "sms"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "What it went or came through. Null until it is sent."
          },
          "sms_retry": {
            "type": "boolean",
            "description": "True when an iMessage that never went was sent again once as a regular text."
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "zapier",
              "make",
              "n8n",
              "pipedream",
              "cli",
              "mcp",
              "hook",
              "broadcast",
              "sequence",
              "inbox",
              "autopilot",
              "keyword",
              "away",
              "widget",
              "assistant",
              "test",
              "mac"
            ],
            "description": "What sent it. Texts read from Messages, including ones you typed by hand, are `mac`."
          },
          "source_ref": {
            "description": "The broadcast, sequence, hook, rule or template behind it, as an id. A text sent with `template_id` carries the template’s `tpl_` id here.",
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "propertyNames": {
              "type": "string",
              "minLength": 1,
              "maxLength": 40
            },
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "description": "Your own data, echoed on the message and on every webhook about it: up to 20 keys of up to 40 characters, each a string of up to 500.",
            "examples": [
              {
                "zap": "new-lead",
                "crm_id": "48213"
              }
            ]
          },
          "hold": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Hold"
              },
              {
                "type": "null"
              }
            ]
          },
          "send_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a scheduled text, when it goes.",
            "examples": [
              null
            ]
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "A text still queued at this time expires.",
            "examples": [
              null
            ]
          },
          "failure": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "enum": [
                      "messages_refused",
                      "not_on_imessage",
                      "file_unavailable"
                    ]
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "reason",
                  "detail"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Why a `failed` text didn’t go. Also set on a `sent` text when the words went and a file didn’t."
          },
          "cancel_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "requested",
                  "opted_out",
                  "sequence_stopped",
                  "broadcast_canceled",
                  "staff"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Why it was canceled: `requested`, `opted_out` (the person texted a stop word), `sequence_stopped`, `broadcast_canceled` or `staff`."
          },
          "resolution": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "marked_sent",
                  "resent"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How an `unconfirmed` text was settled: marked sent, or sent again as a new text."
          },
          "resolved_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was settled.",
            "examples": [
              null
            ]
          },
          "resent_message_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^msg_[0-9A-Za-z]{22}$",
                "description": "A msg_ id.",
                "examples": [
                  "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The new text, when this one was sent again."
          },
          "reply_to_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^msg_[0-9A-Za-z]{22}$",
                "description": "A msg_ id.",
                "examples": [
                  "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The text this one answers inline, when Messages recorded one."
          },
          "reactions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Reaction"
            },
            "description": "Tapbacks on this text that are still there."
          },
          "edited_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was last edited in Messages.",
            "examples": [
              null
            ]
          },
          "unsent_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was unsent in Messages.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When BlueBot accepted or first saw it.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "queued_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it became due.",
            "examples": [
              null
            ]
          },
          "sending_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the Mac took it.",
            "examples": [
              null
            ]
          },
          "sent_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When Messages showed it sent.",
            "examples": [
              null
            ]
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When iMessage showed it delivered. Regular texts are never delivered.",
            "examples": [
              null
            ]
          },
          "read_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was read, where the person shares read receipts.",
            "examples": [
              null
            ]
          },
          "failed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it failed.",
            "examples": [
              null
            ]
          },
          "unconfirmed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the Mac’s lease lapsed without saying whether it went.",
            "examples": [
              null
            ]
          },
          "expired_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it expired.",
            "examples": [
              null
            ]
          },
          "canceled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was canceled.",
            "examples": [
              null
            ]
          },
          "received_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a text in, when it arrived.",
            "examples": [
              null
            ]
          }
        },
        "required": [
          "id",
          "object",
          "direction",
          "state",
          "to",
          "from",
          "chat_id",
          "contact_id",
          "conversation_id",
          "text",
          "text_deleted",
          "files",
          "service_requested",
          "service",
          "sms_retry",
          "source",
          "source_ref",
          "metadata",
          "hold",
          "send_at",
          "expires_at",
          "failure",
          "cancel_reason",
          "resolution",
          "resolved_at",
          "resent_message_id",
          "reply_to_id",
          "reactions",
          "edited_at",
          "unsent_at",
          "created_at",
          "queued_at",
          "sending_at",
          "sent_at",
          "delivered_at",
          "read_at",
          "failed_at",
          "unconfirmed_at",
          "expired_at",
          "canceled_at",
          "received_at"
        ],
        "description": "A text, in or out."
      },
      "Hold": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "enum": [
              "account_held",
              "platform_stopped",
              "plan_lapsed",
              "paused",
              "device_offline",
              "quiet_hours",
              "daily_new_people_limit",
              "platform_daily_limit",
              "pacing"
            ],
            "description": "Why the text is waiting, checked in this order: `account_held` (BlueBot paused the account), `platform_stopped` (BlueBot stopped all sending), `plan_lapsed`, `paused` (you paused sending), `device_offline` (no check-in from the Mac for 2 minutes), `quiet_hours`, `daily_new_people_limit`, `platform_daily_limit` (1,000 a day) and `pacing` (its turn in the spacing between texts)."
          },
          "until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it should stop waiting, when that is known: the end of quiet hours, the next local midnight, or the estimated slot.",
            "examples": [
              null
            ]
          },
          "description": {
            "type": "string",
            "description": "The hold in words.",
            "examples": [
              "Waiting for quiet hours to end at 8:00 AM."
            ]
          }
        },
        "required": [
          "reason",
          "until",
          "description"
        ],
        "description": "A text that is accepted but can’t go yet carries a hold. Null when nothing holds it."
      },
      "Reaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^rxn_[0-9A-Za-z]{22}$",
            "description": "A rxn_ id.",
            "examples": [
              "rxn_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "love",
              "like",
              "dislike",
              "laugh",
              "emphasize",
              "question",
              "emoji"
            ],
            "description": "The tapback: love, like, dislike, laugh, emphasize, question, or a custom emoji."
          },
          "emoji": {
            "description": "The emoji, for `kind: \"emoji\"`.",
            "type": [
              "string",
              "null"
            ]
          },
          "from": {
            "anyOf": [
              {
                "type": "string",
                "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
                "examples": [
                  "+15555550123"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who reacted; null when it was you, on your Mac or iPhone."
          },
          "direction": {
            "type": "string",
            "enum": [
              "in",
              "out"
            ],
            "description": "`in` from the other person, `out` from you."
          },
          "added_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the tapback was added.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "emoji",
          "from",
          "direction",
          "added_at"
        ]
      },
      "File": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^file_[0-9A-Za-z]{22}$",
            "description": "A file_ id.",
            "examples": [
              "file_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "file"
          },
          "name": {
            "description": "The file name, as it was uploaded or as Messages named it.",
            "examples": [
              "IMG_0042.HEIC"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "content_type": {
            "type": "string",
            "description": "The media type.",
            "examples": [
              "image/heic"
            ]
          },
          "size": {
            "type": "integer",
            "description": "Bytes.",
            "examples": [
              2093311
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "image",
              "video",
              "audio",
              "voice_memo",
              "pdf",
              "contact_card",
              "file"
            ],
            "description": "What the file is, for showing it: an image, a video, audio, a voice memo, a PDF, a contact card or another file."
          },
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "waiting",
              "too_large",
              "deleted"
            ],
            "description": "`ready` when BlueBot has the bytes; `waiting` while the Mac uploads them (usually seconds); `too_large` for an attachment over 25 MB, which the Mac never uploads; `deleted` once 30 days have passed."
          },
          "url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "Reads the file for an hour. Null unless `status` is `ready`."
          },
          "url_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When `url` stops working.",
            "examples": [
              null
            ]
          },
          "transcript": {
            "description": "For a voice memo, the words the Mac transcribed on the device, when the owner turned transcription on.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "transcript_language": {
            "description": "The transcript’s language, such as `en-US`.",
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When BlueBot first knew of the file.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "content_type",
          "size",
          "kind",
          "status",
          "url",
          "url_expires_at",
          "transcript",
          "transcript_language",
          "created_at"
        ],
        "description": "A file on a message."
      },
      "Chat": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^chat_[0-9A-Za-z]{22}$",
            "description": "A chat_ id.",
            "examples": [
              "chat_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "chat"
          },
          "name": {
            "description": "The group’s name, when it has one.",
            "examples": [
              "Oak St closing"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "is_group": {
            "type": "boolean"
          },
          "participants": {
            "type": "array",
            "items": {
              "type": "string",
              "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
              "examples": [
                "+15555550123"
              ]
            },
            "description": "The other people in the chat.",
            "examples": [
              [
                "+15555550123",
                "+15555550187"
              ]
            ]
          },
          "service": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "imessage",
                  "sms"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The chat’s service."
          },
          "last_message_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The newest text in the chat.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When BlueBot first saw the chat.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "is_group",
          "participants",
          "service",
          "last_message_at",
          "created_at"
        ],
        "description": "A chat in Messages. BlueBot can send into an existing group chat but can’t start one."
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "contact"
          },
          "handle": {
            "type": "string",
            "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
            "examples": [
              "+15555550123"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "phone",
              "email"
            ],
            "description": "`phone` or `email`."
          },
          "first_name": {
            "examples": [
              "Maria"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "last_name": {
            "examples": [
              "Alvarez"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "examples": [
              null
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The contact’s tags.",
            "examples": [
              [
                "buyer",
                "oak-st"
              ]
            ]
          },
          "custom_fields": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Your own fields, for templates.",
            "examples": [
              {
                "showing": "412 Oak St"
              }
            ]
          },
          "stopped": {
            "type": "boolean",
            "description": "True when the person is on your stop list. Texts to them are canceled."
          },
          "stopped_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When they were put on the stop list.",
            "examples": [
              null
            ]
          },
          "stop_source": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "reply",
                  "dashboard",
                  "api",
                  "import",
                  "admin"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How: `reply` (they texted a stop word), `dashboard`, `api`, `import` or `admin`."
          },
          "last_service": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "imessage",
                  "sms"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The service of the newest text with them."
          },
          "first_message_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The first text either way. Null for somebody you have never texted with, who counts as a new person.",
            "examples": [
              null
            ]
          },
          "last_message_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The newest text either way.",
            "examples": [
              null
            ]
          },
          "created_via": {
            "type": "string",
            "enum": [
              "message",
              "inbound",
              "import",
              "api",
              "dashboard",
              "widget",
              "hook",
              "mcp",
              "assistant"
            ],
            "description": "What first added them."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the contact was added.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "handle",
          "kind",
          "first_name",
          "last_name",
          "company",
          "tags",
          "custom_fields",
          "stopped",
          "stopped_at",
          "stop_source",
          "last_service",
          "first_message_at",
          "last_message_at",
          "created_via",
          "created_at"
        ],
        "description": "A person you text or hear from."
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^conv_[0-9A-Za-z]{22}$",
            "description": "A conv_ id.",
            "examples": [
              "conv_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "conversation"
          },
          "kind": {
            "type": "string",
            "enum": [
              "person",
              "group"
            ],
            "description": "`person` for one person, `group` for a group chat."
          },
          "title": {
            "type": "string",
            "description": "The person’s name, the group’s name, or their numbers, as the inbox shows it.",
            "examples": [
              "Marcus Lee"
            ]
          },
          "handle": {
            "description": "The person’s phone number or email address; null for a group.",
            "examples": [
              "+15555550123"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "contact_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^ct_[0-9A-Za-z]{22}$",
                "description": "A ct_ id.",
                "examples": [
                  "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The person, for a one-to-one conversation."
          },
          "chat_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^chat_[0-9A-Za-z]{22}$",
                "description": "A chat_ id.",
                "examples": [
                  "chat_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The group chat, for a group."
          },
          "participants": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Everyone in it besides you: one handle for a person, the members for a group."
          },
          "service": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "imessage",
                  "sms"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The service the last text used, when known."
          },
          "last_message": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^msg_[0-9A-Za-z]{22}$",
                    "description": "A msg_ id.",
                    "examples": [
                      "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                    ]
                  },
                  "direction": {
                    "type": "string",
                    "enum": [
                      "in",
                      "out"
                    ]
                  },
                  "state": {
                    "type": "string",
                    "description": "The last text’s state."
                  },
                  "preview": {
                    "description": "Its first 140 characters, or null when it had no words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "files": {
                    "type": "integer",
                    "description": "How many files it carried."
                  },
                  "at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it was sent or arrived.",
                    "examples": [
                      "2026-11-13T19:41:00.000Z"
                    ]
                  }
                },
                "required": [
                  "id",
                  "direction",
                  "state",
                  "preview",
                  "files",
                  "at"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "last_message_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the last text was sent or arrived.",
            "examples": [
              null
            ]
          },
          "unread_count": {
            "type": "integer",
            "description": "Texts in that you haven’t opened in the dashboard."
          },
          "waiting": {
            "type": "boolean",
            "description": "True when the last text is theirs, so they are waiting on you."
          },
          "archived": {
            "type": "boolean",
            "description": "Marked done. A new text in brings it back."
          },
          "stopped": {
            "type": "boolean",
            "description": "The person is on your stop list."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the conversation started.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "kind",
          "title",
          "handle",
          "contact_id",
          "chat_id",
          "participants",
          "service",
          "last_message",
          "last_message_at",
          "unread_count",
          "waiting",
          "archived",
          "stopped",
          "created_at"
        ],
        "description": "A conversation with one person or one group chat."
      },
      "Template": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^tpl_[0-9A-Za-z]{22}$",
            "description": "A tpl_ id.",
            "examples": [
              "tpl_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "template"
          },
          "name": {
            "type": "string",
            "description": "Its name, unique among your templates.",
            "examples": [
              "Showing reminder"
            ]
          },
          "body": {
            "type": "string",
            "description": "The text, with `{{variables}}` and `{{variable|fallback}}`.",
            "examples": [
              "Hi {{first_name|there}}, see you at {{showing}} tomorrow."
            ]
          },
          "variables": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The variables the text names, in order, once each.",
            "examples": [
              [
                "first_name",
                "showing"
              ]
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it last changed.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "body",
          "variables",
          "created_at",
          "updated_at"
        ],
        "description": "A saved text. A variable is a contact field (`first_name`, `last_name`, `company`), a custom field, or a value you pass; `|` gives a fallback for when it is empty."
      },
      "Stop": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "stop"
          },
          "handle": {
            "type": "string",
            "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
            "examples": [
              "+15555550123"
            ]
          },
          "contact_id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "stopped_at": {
            "type": "string",
            "format": "date-time",
            "description": "When they were put on the list.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "reply",
              "dashboard",
              "api",
              "import",
              "admin"
            ],
            "description": "`reply` (they texted a stop word), `dashboard`, `api`, `import` or `admin`."
          }
        },
        "required": [
          "object",
          "handle",
          "contact_id",
          "stopped_at",
          "source"
        ],
        "description": "A person BlueBot won’t text. Texts to them are canceled with `cancel_reason: \"opted_out\"`."
      },
      "Lookup": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "lookup"
          },
          "handle": {
            "type": "string",
            "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
            "examples": [
              "+15555550123"
            ]
          },
          "service": {
            "type": "string",
            "enum": [
              "imessage",
              "sms",
              "unknown"
            ],
            "description": "What the newest chat with the person used, or `unknown`."
          },
          "basis": {
            "type": "string",
            "enum": [
              "history",
              "none",
              "device_offline",
              "timeout"
            ],
            "description": "`history`: a chat with the person was found. `none`: there is no chat with them. `device_offline`: the Mac wasn’t there to ask. `timeout`: the Mac didn’t answer within 15 seconds."
          },
          "last_seen_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The newest text in that chat.",
            "examples": [
              null
            ]
          },
          "checked_at": {
            "type": "string",
            "format": "date-time",
            "description": "When this answer was found.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "object",
          "handle",
          "service",
          "basis",
          "last_seen_at",
          "checked_at"
        ],
        "description": "A best guess at whether a person uses iMessage, with what it is based on. BlueBot can only read your own history."
      },
      "Device": {
        "type": "object",
        "properties": {
          "id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^dev_[0-9A-Za-z]{22}$",
                "description": "A dev_ id.",
                "examples": [
                  "dev_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Null until a Mac is connected."
          },
          "object": {
            "type": "string",
            "const": "device"
          },
          "status": {
            "type": "string",
            "enum": [
              "online",
              "offline",
              "never_connected"
            ],
            "description": "`online` (checked in within 2 minutes), `offline` or `never_connected`."
          },
          "name": {
            "examples": [
              "Dana’s MacBook Air"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "description": "The phone number Messages on the Mac sends from, when it can tell.",
            "examples": [
              "+15555550100"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "app_version": {
            "examples": [
              "1.0.0"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "macos_version": {
            "examples": [
              "15.1"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "last_seen_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Mac’s last check-in.",
            "examples": [
              null
            ]
          },
          "last_sync_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last time the Mac finished posting the texts it read from Messages.",
            "examples": [
              null
            ]
          },
          "offline_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the Mac went quiet, while it is offline.",
            "examples": [
              null
            ]
          },
          "paired_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this Mac was connected.",
            "examples": [
              null
            ]
          },
          "checks": {
            "type": "object",
            "properties": {
              "messages": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "full_disk_access": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "forwarding": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "awake": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "filevault": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              }
            },
            "required": [
              "messages",
              "full_disk_access",
              "forwarding",
              "awake",
              "filevault"
            ],
            "description": "The Mac’s setup checks: Messages signed in, Full Disk Access, Text Message Forwarding, staying awake, FileVault."
          },
          "checks_ok": {
            "description": "True when no check needs you.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "transcription": {
            "type": "boolean",
            "description": "Whether voice memos are transcribed on this Mac."
          },
          "held_count": {
            "type": "integer",
            "description": "Queued texts that are waiting on a hold."
          },
          "queued_count": {
            "type": "integer",
            "description": "Every queued text."
          },
          "unconfirmed_count": {
            "type": "integer",
            "description": "Texts the Mac couldn’t confirm, waiting for you to settle them."
          },
          "paused_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "While you have sending paused, until when.",
            "examples": [
              null
            ]
          },
          "today": {
            "type": "object",
            "properties": {
              "sent": {
                "type": "integer",
                "description": "Texts the Mac took today, in your time zone."
              },
              "new_people": {
                "type": "integer",
                "description": "People texted for the first time today."
              },
              "new_people_limit": {
                "type": "integer",
                "description": "Your new-people-per-day setting."
              },
              "daily_limit": {
                "type": "integer",
                "description": "BlueBot’s ceiling on texts a day."
              },
              "resets_at": {
                "type": "string",
                "format": "date-time",
                "description": "The next local midnight, when the counts start again.",
                "examples": [
                  "2026-11-13T19:41:00.000Z"
                ]
              }
            },
            "required": [
              "sent",
              "new_people",
              "new_people_limit",
              "daily_limit",
              "resets_at"
            ],
            "description": "Today’s counts against the limits."
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "name",
          "number",
          "app_version",
          "macos_version",
          "last_seen_at",
          "last_sync_at",
          "offline_since",
          "paired_at",
          "checks",
          "checks_ok",
          "transcription",
          "held_count",
          "queued_count",
          "unconfirmed_count",
          "paused_until",
          "today"
        ],
        "description": "The Mac that sends for this account. An account has one."
      },
      "Settings": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "settings"
          },
          "business_name": {
            "description": "Your business’s name, which `{{business}}` fills in. Null until you set it; texts that would name the business leave it out until then.",
            "examples": [
              "Dana Realty"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "time_zone": {
            "type": "string",
            "description": "The zone quiet hours and daily limits are read in.",
            "examples": [
              "America/Chicago"
            ]
          },
          "pace_seconds": {
            "type": "integer",
            "description": "Seconds between two texts leaving the Mac, 5 to 300.",
            "examples": [
              20
            ]
          },
          "new_people_per_day": {
            "type": "integer",
            "description": "How many people you have never texted with BlueBot may be texted in a day, 0 to 1,000.",
            "examples": [
              50
            ]
          },
          "quiet_hours": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean"
              },
              "start": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                "description": "When quiet hours start, in `time_zone`.",
                "examples": [
                  "21:00"
                ]
              },
              "end": {
                "type": "string",
                "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
                "description": "When they end.",
                "examples": [
                  "08:00"
                ]
              }
            },
            "required": [
              "enabled",
              "start",
              "end"
            ]
          },
          "smart_quiet_hours": {
            "type": "boolean",
            "description": "Read quiet hours in the recipient’s zone, from their area code, where BlueBot knows it."
          },
          "stop_words": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "description": "Whether a reply of only a stop word puts the person on the stop list."
              },
              "words": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "The stop words: your own list, or the defaults when `custom` is false."
              },
              "custom": {
                "type": "boolean",
                "description": "Whether you changed the list. False means BlueBot’s defaults."
              },
              "start_words": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Words that take a person who stopped by reply off the list again."
              }
            },
            "required": [
              "enabled",
              "words",
              "custom",
              "start_words"
            ]
          },
          "expiry_hours": {
            "type": "integer",
            "description": "A text still waiting this long after it was due expires, 1 to 168.",
            "examples": [
              24
            ]
          },
          "inbound_mode": {
            "type": "string",
            "enum": [
              "replies",
              "everything"
            ],
            "description": "Which chats the Mac copies to BlueBot: `replies` (people BlueBot has texted) or `everything`."
          },
          "paused_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "While you have sending paused, until when.",
            "examples": [
              null
            ]
          },
          "platform_daily_limit": {
            "type": "integer",
            "description": "BlueBot’s ceiling on texts a day, which you can’t change."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Things worth knowing about these settings, in words."
          }
        },
        "required": [
          "object",
          "business_name",
          "time_zone",
          "pace_seconds",
          "new_people_per_day",
          "quiet_hours",
          "smart_quiet_hours",
          "stop_words",
          "expiry_hours",
          "inbound_mode",
          "paused_until",
          "platform_daily_limit",
          "warnings"
        ],
        "description": "The sending rules. Each is yours to change."
      },
      "Me": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "me"
          },
          "account": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^acct_[0-9A-Za-z]{22}$",
                "description": "A acct_ id.",
                "examples": [
                  "acct_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              "email": {
                "type": "string",
                "examples": [
                  "dana@example.com"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "time_zone": {
                "type": "string"
              },
              "created_at": {
                "type": "string",
                "format": "date-time",
                "description": "When the account was made.",
                "examples": [
                  "2026-11-13T19:41:00.000Z"
                ]
              }
            },
            "required": [
              "id",
              "email",
              "name",
              "time_zone",
              "created_at"
            ]
          },
          "key": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^key_[0-9A-Za-z]{22}$",
                    "description": "A key_ id.",
                    "examples": [
                      "key_1Hq2LxW9cVbN3mKpRtYs0a"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "examples": [
                      "Zapier"
                    ]
                  },
                  "prefix": {
                    "type": "string",
                    "description": "The start of the key, to tell keys apart.",
                    "examples": [
                      "bb_live_7Hq2Lx"
                    ]
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "live",
                      "test"
                    ]
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "messages:send",
                        "messages:read",
                        "contacts:write",
                        "contacts:read",
                        "webhooks:manage",
                        "account:read"
                      ]
                    }
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the key was made.",
                    "examples": [
                      "2026-11-13T19:41:00.000Z"
                    ]
                  }
                },
                "required": [
                  "id",
                  "name",
                  "prefix",
                  "mode",
                  "scopes",
                  "created_at"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The key the request carried; null for other kinds of sign-in."
          },
          "plan": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "trialing",
                      "active",
                      "past_due",
                      "canceled",
                      "unpaid",
                      "incomplete",
                      "incomplete_expired",
                      "paused"
                    ]
                  },
                  "active": {
                    "type": "boolean",
                    "description": "Whether texts can go."
                  },
                  "trial_end": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "When the trial ends.",
                    "examples": [
                      null
                    ]
                  },
                  "current_period_end": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "When the current month ends.",
                    "examples": [
                      null
                    ]
                  }
                },
                "required": [
                  "status",
                  "active",
                  "trial_end",
                  "current_period_end"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "device": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "online",
                  "offline",
                  "never_connected"
                ]
              }
            },
            "required": [
              "status"
            ]
          }
        },
        "required": [
          "object",
          "account",
          "key",
          "plan",
          "device"
        ],
        "description": "The account and key a request acts as."
      },
      "Status": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "status"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded",
              "down"
            ],
            "description": "`ok`; `degraded` when BlueBot stopped sending for everyone; `down` when it can’t reach its database."
          },
          "sending": {
            "type": "string",
            "enum": [
              "ok",
              "stopped",
              "unknown"
            ],
            "description": "`ok`; `stopped` while BlueBot has stopped all sending, during an incident; `unknown` when BlueBot can’t reach its database to check. Macs can’t pick up texts while the database is down, so queued texts wait."
          },
          "database": {
            "type": "string",
            "enum": [
              "ok",
              "down"
            ]
          },
          "api_version": {
            "type": "string",
            "examples": [
              "2026-11-13"
            ]
          },
          "checked_at": {
            "type": "string",
            "format": "date-time",
            "description": "When this was checked.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "object",
          "status",
          "sending",
          "database",
          "api_version",
          "checked_at"
        ],
        "description": "Whether BlueBot itself is up. Says nothing about any one Mac; for that, see `GET /v1/device`."
      },
      "Analytics": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "analytics"
          },
          "days": {
            "type": "integer"
          },
          "time_zone": {
            "type": "string"
          },
          "from": {
            "type": "string",
            "format": "date-time",
            "description": "The start of the first day covered, local midnight in `time_zone`.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "to": {
            "type": "string",
            "format": "date-time",
            "description": "The time the numbers were read.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "first_text_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the account’s first text went or came in; null before any.",
            "examples": [
              null
            ]
          },
          "totals": {
            "type": "object",
            "properties": {
              "sent": {
                "type": "integer",
                "description": "Texts that left the Mac (sent, delivered or read), by when they went."
              },
              "received": {
                "type": "integer",
                "description": "Texts people sent you, by when they came in."
              },
              "delivered": {
                "type": "integer",
                "description": "Sent texts that reported delivered or read."
              },
              "read": {
                "type": "integer",
                "description": "Sent texts that reported read."
              },
              "failed": {
                "type": "integer",
                "description": "Texts that failed."
              },
              "unconfirmed": {
                "type": "integer",
                "description": "Texts the Mac couldn’t confirm, by when they were handed to it."
              },
              "canceled": {
                "type": "integer",
                "description": "Texts canceled before they went."
              },
              "expired": {
                "type": "integer",
                "description": "Texts that waited past their expiry."
              },
              "people_texted": {
                "type": "integer",
                "description": "People you texted one to one."
              },
              "people_replied": {
                "type": "integer",
                "description": "Of them, people who texted back within `reply_window_hours`."
              },
              "new_people": {
                "type": "integer",
                "description": "People texted for the first time."
              },
              "stops": {
                "type": "integer",
                "description": "People who asked to stop, by reply or added by you."
              }
            },
            "required": [
              "sent",
              "received",
              "delivered",
              "read",
              "failed",
              "unconfirmed",
              "canceled",
              "expired",
              "people_texted",
              "people_replied",
              "new_people",
              "stops"
            ],
            "description": "Counts over the range."
          },
          "delivery_rate": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "Delivered or read, out of texts that left the Mac or failed. Canceled, expired, waiting and unconfirmed texts aren’t counted. A fraction from 0 to 1; null when there is nothing to count yet."
          },
          "reply_rate": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "People texted one to one who texted back within `reply_window_hours` of a text. A fraction from 0 to 1; null when there is nothing to count yet."
          },
          "reply_window_hours": {
            "type": "integer"
          },
          "response_times": {
            "type": "object",
            "properties": {
              "them_median_seconds": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "How long people take to answer you: from your text to their next one. In seconds; null when there are no replies to measure."
              },
              "them_count": {
                "type": "integer",
                "description": "Replies measured."
              },
              "you_median_seconds": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "How long you take to answer them: from their text to your next one. Away messages and keyword replies aren’t counted. In seconds; null when there are no replies to measure."
              },
              "you_count": {
                "type": "integer"
              }
            },
            "required": [
              "them_median_seconds",
              "them_count",
              "you_median_seconds",
              "you_count"
            ]
          },
          "services": {
            "type": "object",
            "properties": {
              "imessage": {
                "type": "integer"
              },
              "sms": {
                "type": "integer"
              }
            },
            "required": [
              "imessage",
              "sms"
            ],
            "description": "Texts that left the Mac, by the service they went as. RCS counts as SMS."
          },
          "by_day": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "day": {
                  "type": "string",
                  "description": "YYYY-MM-DD in `time_zone`."
                },
                "sent": {
                  "type": "integer"
                },
                "received": {
                  "type": "integer"
                }
              },
              "required": [
                "day",
                "sent",
                "received"
              ]
            }
          },
          "by_hour": {
            "minItems": 7,
            "maxItems": 7,
            "type": "array",
            "items": {
              "minItems": 24,
              "maxItems": 24,
              "type": "array",
              "items": {
                "type": "integer"
              }
            },
            "description": "Texts in and out by weekday (Monday first) and hour, in `time_zone`."
          },
          "by_source": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "source": {
                  "type": "string",
                  "enum": [
                    "api",
                    "zapier",
                    "make",
                    "n8n",
                    "pipedream",
                    "cli",
                    "mcp",
                    "hook",
                    "broadcast",
                    "sequence",
                    "inbox",
                    "autopilot",
                    "keyword",
                    "away",
                    "widget",
                    "assistant",
                    "test",
                    "mac"
                  ]
                },
                "count": {
                  "type": "integer"
                }
              },
              "required": [
                "source",
                "count"
              ]
            },
            "description": "Texts that left the Mac by where they came from, most first."
          },
          "health": {
            "type": "object",
            "properties": {
              "waiting": {
                "type": "integer",
                "description": "Conversations whose last text is theirs and has no answer from you."
              },
              "follow_up_gaps": {
                "type": "integer",
                "description": "Of those, people who answered a text of yours and have heard nothing for two days."
              },
              "oldest_waiting_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "When the longest-waiting of those texts came in.",
                "examples": [
                  null
                ]
              },
              "waiting_list": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/WaitingConversation"
                },
                "description": "Up to 10 conversations waiting on you, follow-up gaps and oldest first."
              },
              "unconfirmed": {
                "type": "integer",
                "description": "Texts waiting for you to say whether they went."
              },
              "held": {
                "type": "integer",
                "description": "Queued texts held by a rule, not just waiting their turn."
              }
            },
            "required": [
              "waiting",
              "follow_up_gaps",
              "oldest_waiting_at",
              "waiting_list",
              "unconfirmed",
              "held"
            ]
          },
          "fixes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnalyticsFix"
            },
            "description": "What to fix next, most important first."
          }
        },
        "required": [
          "object",
          "days",
          "time_zone",
          "from",
          "to",
          "first_text_at",
          "totals",
          "delivery_rate",
          "reply_rate",
          "reply_window_hours",
          "response_times",
          "services",
          "by_day",
          "by_hour",
          "by_source",
          "health",
          "fixes"
        ],
        "description": "Texting numbers for a range of days, read in the account’s time zone."
      },
      "AnalyticsFix": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "enum": [
              "follow_up_gaps",
              "waiting",
              "unconfirmed",
              "failed",
              "held",
              "mac_checks",
              "mac_offline",
              "delivery",
              "stops",
              "slow_replies"
            ]
          },
          "title": {
            "type": "string",
            "description": "What needs doing, in a sentence."
          },
          "why": {
            "type": "string",
            "description": "Why it matters, in a sentence."
          },
          "count": {
            "type": "integer"
          },
          "href": {
            "type": "string",
            "description": "The dashboard page where it is fixed."
          },
          "severity": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ]
          }
        },
        "required": [
          "key",
          "title",
          "why",
          "count",
          "href",
          "severity"
        ]
      },
      "WaitingConversation": {
        "type": "object",
        "properties": {
          "conversation_id": {
            "type": "string",
            "pattern": "^conv_[0-9A-Za-z]{22}$",
            "description": "A conv_ id.",
            "examples": [
              "conv_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "name": {
            "type": "string",
            "description": "The person’s name, the group’s name, or their number when there is no name."
          },
          "handle": {
            "description": "Their number or email address; null for a group chat.",
            "type": [
              "string",
              "null"
            ]
          },
          "is_group": {
            "type": "boolean"
          },
          "since": {
            "type": "string",
            "format": "date-time",
            "description": "When their last text came in.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "follow_up_gap": {
            "type": "boolean",
            "description": "True when they answered a text of yours and have heard nothing for two days."
          }
        },
        "required": [
          "conversation_id",
          "name",
          "handle",
          "is_group",
          "since",
          "follow_up_gap"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_[0-9A-Za-z]{22}$",
            "description": "The event id. A webhook delivery sends it as `webhook-id`, the same on every retry, so a receiver can skip one it already has.",
            "examples": [
              "evt_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "event"
          },
          "type": {
            "type": "string",
            "enum": [
              "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"
            ]
          },
          "api_version": {
            "type": "string",
            "description": "The payload version: the one the receiving webhook was made with.",
            "examples": [
              "2026-11-13"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When it happened.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "test": {
            "description": "Present, and `true`, only on a test event from **Send test event** or `POST /v1/webhooks/{id}/test`. Its `data` is the catalog’s example, with example ids that match nothing on your account. Real events never have it.",
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {},
            "description": "The record as the API returned it at the time. Each type’s shape is in the event catalog."
          }
        },
        "required": [
          "id",
          "object",
          "type",
          "api_version",
          "timestamp",
          "data"
        ],
        "description": "Something that happened on the account."
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^wh_[0-9A-Za-z]{22}$",
            "description": "A wh_ id.",
            "examples": [
              "wh_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "webhook"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "examples": [
              "https://hooks.zapier.com/hooks/standard/1234567/abcdef/"
            ]
          },
          "description": {
            "examples": [
              "New replies to my CRM"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "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"
              ]
            },
            "description": "The event types it receives. For a webhook made with `[\"*\"]`, every type there is now."
          },
          "all_events": {
            "type": "boolean",
            "description": "True when it was made with `[\"*\"]`: it also receives event types BlueBot adds later."
          },
          "api_version": {
            "type": "string",
            "description": "The payload version it was made with and keeps.",
            "examples": [
              "2026-11-13"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "failing",
              "paused"
            ],
            "description": "`active`; `failing` while deliveries fail (retried for about 3 days); `paused` by you, or after 72 hours with no successful answer."
          },
          "paused_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was paused.",
            "examples": [
              null
            ]
          },
          "pause_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "failing",
                  "customer",
                  "staff"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who paused it: `failing` (72 hours of failures), `customer` or `staff`."
          },
          "failing_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The first failure since the last success.",
            "examples": [
              null
            ]
          },
          "last_success_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last delivery answered with a 2xx.",
            "examples": [
              null
            ]
          },
          "last_failure_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last delivery that failed.",
            "examples": [
              null
            ]
          },
          "last_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The HTTP status of the last answer."
          },
          "previous_secret_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "After a rotation, when the old secret stops signing alongside the new one.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "url",
          "description",
          "events",
          "all_events",
          "api_version",
          "status",
          "paused_at",
          "pause_reason",
          "failing_since",
          "last_success_at",
          "last_failure_at",
          "last_status",
          "previous_secret_expires_at",
          "created_at"
        ],
        "description": "An address BlueBot posts events to, signed the Standard Webhooks way."
      },
      "WebhookWithSecret": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^wh_[0-9A-Za-z]{22}$",
            "description": "A wh_ id.",
            "examples": [
              "wh_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "webhook"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "examples": [
              "https://hooks.zapier.com/hooks/standard/1234567/abcdef/"
            ]
          },
          "description": {
            "examples": [
              "New replies to my CRM"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "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"
              ]
            },
            "description": "The event types it receives. For a webhook made with `[\"*\"]`, every type there is now."
          },
          "all_events": {
            "type": "boolean",
            "description": "True when it was made with `[\"*\"]`: it also receives event types BlueBot adds later."
          },
          "api_version": {
            "type": "string",
            "description": "The payload version it was made with and keeps.",
            "examples": [
              "2026-11-13"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "failing",
              "paused"
            ],
            "description": "`active`; `failing` while deliveries fail (retried for about 3 days); `paused` by you, or after 72 hours with no successful answer."
          },
          "paused_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it was paused.",
            "examples": [
              null
            ]
          },
          "pause_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "failing",
                  "customer",
                  "staff"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who paused it: `failing` (72 hours of failures), `customer` or `staff`."
          },
          "failing_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The first failure since the last success.",
            "examples": [
              null
            ]
          },
          "last_success_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last delivery answered with a 2xx.",
            "examples": [
              null
            ]
          },
          "last_failure_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last delivery that failed.",
            "examples": [
              null
            ]
          },
          "last_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The HTTP status of the last answer."
          },
          "previous_secret_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "After a rotation, when the old secret stops signing alongside the new one.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "secret": {
            "type": "string",
            "description": "The signing secret, `whsec_` and base64. Verify `webhook-signature` with it. Shown when the webhook is made and when the secret is rotated.",
            "examples": [
              "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "url",
          "description",
          "events",
          "all_events",
          "api_version",
          "status",
          "paused_at",
          "pause_reason",
          "failing_since",
          "last_success_at",
          "last_failure_at",
          "last_status",
          "previous_secret_expires_at",
          "created_at",
          "secret"
        ]
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^dlv_[0-9A-Za-z]{22}$",
            "description": "A dlv_ id.",
            "examples": [
              "dlv_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "webhook_delivery"
          },
          "webhook_id": {
            "type": "string",
            "pattern": "^wh_[0-9A-Za-z]{22}$",
            "description": "A wh_ id.",
            "examples": [
              "wh_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "event_id": {
            "type": "string",
            "pattern": "^evt_[0-9A-Za-z]{22}$",
            "description": "A evt_ id.",
            "examples": [
              "evt_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "event_type": {
            "type": "string",
            "enum": [
              "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"
            ]
          },
          "test": {
            "type": "boolean",
            "description": "True for an example sent with `POST /v1/webhooks/{id}/test`."
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "delivered",
              "gave_up",
              "dropped"
            ],
            "description": "`pending` (trying, or waiting to try again), `delivered`, `gave_up` after the last retry, or `dropped`."
          },
          "attempts": {
            "type": "integer"
          },
          "last_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "The HTTP status of the last try."
          },
          "last_error": {
            "description": "Why the last try failed, when there was no answer.",
            "type": [
              "string",
              "null"
            ]
          },
          "last_duration_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_response_body": {
            "description": "The first 2 KB of what your endpoint answered on the last try, as text. Null when it answered with no body or not at all.",
            "type": [
              "string",
              "null"
            ]
          },
          "next_attempt_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it is tried next, while pending.",
            "examples": [
              null
            ]
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When a 2xx answered it.",
            "examples": [
              null
            ]
          },
          "replay_of": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^dlv_[0-9A-Za-z]{22}$",
                "description": "A dlv_ id.",
                "examples": [
                  "dlv_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The delivery this one repeats, for a replay."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "webhook_id",
          "event_id",
          "event_type",
          "test",
          "state",
          "attempts",
          "last_status",
          "last_error",
          "last_duration_ms",
          "last_response_body",
          "next_attempt_at",
          "delivered_at",
          "replay_of",
          "created_at"
        ],
        "description": "One try, or series of tries, to deliver one event to one webhook."
      },
      "ReactionEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^rxn_[0-9A-Za-z]{22}$",
            "description": "A rxn_ id.",
            "examples": [
              "rxn_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "love",
              "like",
              "dislike",
              "laugh",
              "emphasize",
              "question",
              "emoji"
            ],
            "description": "The tapback: love, like, dislike, laugh, emphasize, question, or a custom emoji."
          },
          "emoji": {
            "description": "The emoji, for `kind: \"emoji\"`.",
            "type": [
              "string",
              "null"
            ]
          },
          "from": {
            "anyOf": [
              {
                "type": "string",
                "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
                "examples": [
                  "+15555550123"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Who reacted; null when it was you, on your Mac or iPhone."
          },
          "direction": {
            "type": "string",
            "enum": [
              "in",
              "out"
            ],
            "description": "`in` from the other person, `out` from you."
          },
          "added_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the tapback was added.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "object": {
            "type": "string",
            "const": "reaction"
          },
          "message_id": {
            "type": "string",
            "pattern": "^msg_[0-9A-Za-z]{22}$",
            "description": "The text the tapback is on.",
            "examples": [
              "msg_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "conversation_id": {
            "type": "string",
            "pattern": "^conv_[0-9A-Za-z]{22}$",
            "description": "A conv_ id.",
            "examples": [
              "conv_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "chat_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^chat_[0-9A-Za-z]{22}$",
                "description": "A chat_ id.",
                "examples": [
                  "chat_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "contact_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^ct_[0-9A-Za-z]{22}$",
                "description": "A ct_ id.",
                "examples": [
                  "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "The person who reacted, or for your own tapback, the person you were texting."
          },
          "removed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "For `reaction.removed`, when it was taken back.",
            "examples": [
              null
            ]
          }
        },
        "required": [
          "id",
          "kind",
          "emoji",
          "from",
          "direction",
          "added_at",
          "object",
          "message_id",
          "conversation_id",
          "chat_id",
          "contact_id",
          "removed_at"
        ],
        "description": "A tapback on a text."
      },
      "EnrollmentEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^enr_[0-9A-Za-z]{22}$",
            "description": "A enr_ id.",
            "examples": [
              "enr_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "enrollment"
          },
          "sequence_id": {
            "type": "string",
            "pattern": "^seq_[0-9A-Za-z]{22}$",
            "description": "A seq_ id.",
            "examples": [
              "seq_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "contact_id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "handle": {
            "type": "string",
            "description": "The person’s phone number or email address, as `to` takes it.",
            "examples": [
              "+15555550123"
            ]
          },
          "contact": {
            "description": "The person, as the contact events carry them.",
            "$ref": "#/components/schemas/Contact"
          },
          "state": {
            "type": "string",
            "enum": [
              "completed",
              "stopped",
              "canceled"
            ]
          },
          "stop_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "replied",
                  "stopped",
                  "canceled",
                  "sequence_archived",
                  "failed"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Why it ended early, when it did."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it ended.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "sequence_id",
          "contact_id",
          "handle",
          "contact",
          "state",
          "stop_reason",
          "completed_at"
        ],
        "description": "A person’s run through a sequence."
      },
      "BroadcastEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^bc_[0-9A-Za-z]{22}$",
            "description": "A bc_ id.",
            "examples": [
              "bc_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "broadcast"
          },
          "name": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "completed",
              "canceled"
            ]
          },
          "recipient_count": {
            "type": "integer"
          },
          "counts": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer"
            },
            "description": "How many texts ended in each state: `sent`, `delivered`, `failed`, `skipped` and so on."
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the last text settled.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "state",
          "recipient_count",
          "counts",
          "completed_at"
        ],
        "description": "A text sent to a list, once every text in it has settled."
      },
      "DeviceEvent": {
        "type": "object",
        "properties": {
          "id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^dev_[0-9A-Za-z]{22}$",
                "description": "A dev_ id.",
                "examples": [
                  "dev_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Null until a Mac is connected."
          },
          "object": {
            "type": "string",
            "const": "device"
          },
          "status": {
            "type": "string",
            "enum": [
              "online",
              "offline",
              "never_connected"
            ],
            "description": "`online` (checked in within 2 minutes), `offline` or `never_connected`."
          },
          "name": {
            "examples": [
              "Dana’s MacBook Air"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "number": {
            "description": "The phone number Messages on the Mac sends from, when it can tell.",
            "examples": [
              "+15555550100"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "app_version": {
            "examples": [
              "1.0.0"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "macos_version": {
            "examples": [
              "15.1"
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "last_seen_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The Mac’s last check-in.",
            "examples": [
              null
            ]
          },
          "last_sync_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "The last time the Mac finished posting the texts it read from Messages.",
            "examples": [
              null
            ]
          },
          "offline_since": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the Mac went quiet, while it is offline.",
            "examples": [
              null
            ]
          },
          "paired_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this Mac was connected.",
            "examples": [
              null
            ]
          },
          "checks": {
            "type": "object",
            "properties": {
              "messages": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "full_disk_access": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "forwarding": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "awake": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              },
              "filevault": {
                "type": "object",
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "ok",
                      "needs_you",
                      "unknown"
                    ],
                    "description": "`ok`, `needs_you` (something on the Mac needs fixing) or `unknown`."
                  },
                  "detail": {
                    "description": "What the Mac saw, in words.",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "state",
                  "detail"
                ]
              }
            },
            "required": [
              "messages",
              "full_disk_access",
              "forwarding",
              "awake",
              "filevault"
            ],
            "description": "The Mac’s setup checks: Messages signed in, Full Disk Access, Text Message Forwarding, staying awake, FileVault."
          },
          "checks_ok": {
            "description": "True when no check needs you.",
            "type": [
              "boolean",
              "null"
            ]
          },
          "transcription": {
            "type": "boolean",
            "description": "Whether voice memos are transcribed on this Mac."
          },
          "held_count": {
            "type": "integer",
            "description": "Queued texts that are waiting on a hold."
          },
          "queued_count": {
            "type": "integer",
            "description": "Every queued text."
          },
          "unconfirmed_count": {
            "type": "integer",
            "description": "Texts the Mac couldn’t confirm, waiting for you to settle them."
          },
          "paused_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "While you have sending paused, until when.",
            "examples": [
              null
            ]
          },
          "today": {
            "type": "object",
            "properties": {
              "sent": {
                "type": "integer",
                "description": "Texts the Mac took today, in your time zone."
              },
              "new_people": {
                "type": "integer",
                "description": "People texted for the first time today."
              },
              "new_people_limit": {
                "type": "integer",
                "description": "Your new-people-per-day setting."
              },
              "daily_limit": {
                "type": "integer",
                "description": "BlueBot’s ceiling on texts a day."
              },
              "resets_at": {
                "type": "string",
                "format": "date-time",
                "description": "The next local midnight, when the counts start again.",
                "examples": [
                  "2026-11-13T19:41:00.000Z"
                ]
              }
            },
            "required": [
              "sent",
              "new_people",
              "new_people_limit",
              "daily_limit",
              "resets_at"
            ],
            "description": "Today’s counts against the limits."
          },
          "failed_checks": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "messages",
                "full_disk_access",
                "forwarding",
                "awake",
                "filevault"
              ]
            },
            "description": "For `device.check_failed`, the checks that just turned `needs_you`; empty otherwise."
          }
        },
        "required": [
          "id",
          "object",
          "status",
          "name",
          "number",
          "app_version",
          "macos_version",
          "last_seen_at",
          "last_sync_at",
          "offline_since",
          "paired_at",
          "checks",
          "checks_ok",
          "transcription",
          "held_count",
          "queued_count",
          "unconfirmed_count",
          "paused_until",
          "today",
          "failed_checks"
        ]
      },
      "Broadcast": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^bc_[0-9A-Za-z]{22}$",
            "description": "A bc_ id.",
            "examples": [
              "bc_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "broadcast"
          },
          "name": {
            "type": "string",
            "examples": [
              "Open house Saturday"
            ]
          },
          "text": {
            "description": "The words, with `{{variables}}`, as you wrote them. Each person’s filled-in text is on their message. Null once they’re deleted, 30 days after the broadcast finished.",
            "examples": [
              "Hi {{first_name|there}}, open house at 412 Oak St this Saturday 1–4."
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "text_deleted": {
            "type": "boolean",
            "description": "True once the words, and the values each person’s list row brought, were deleted 30 days after the broadcast finished."
          },
          "template_id": {
            "description": "The template the words came from, when one did.",
            "type": [
              "string",
              "null"
            ]
          },
          "audience": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "const": "tags"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Contacts with any of these tags."
                  }
                },
                "required": [
                  "kind",
                  "tags"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "const": "contacts"
                  },
                  "contact_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "pattern": "^ct_[0-9A-Za-z]{22}$",
                      "description": "A ct_ id.",
                      "examples": [
                        "ct_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    },
                    "description": "These contacts."
                  }
                },
                "required": [
                  "kind",
                  "contact_ids"
                ]
              },
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "const": "list"
                  },
                  "count": {
                    "type": "integer",
                    "description": "How many people were in the list or CSV."
                  },
                  "columns": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "The variables each row brought, for the template."
                  }
                },
                "required": [
                  "kind",
                  "count",
                  "columns"
                ]
              }
            ],
            "description": "Who the broadcast goes to."
          },
          "service": {
            "type": "string",
            "enum": [
              "auto",
              "imessage",
              "sms"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "sending",
              "completed",
              "canceled"
            ],
            "description": "`draft`, `scheduled` (waiting for `send_at`), `sending`, `completed` or `canceled`."
          },
          "send_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it starts, for a scheduled broadcast.",
            "examples": [
              null
            ]
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the first text was queued.",
            "examples": [
              null
            ]
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When every text had settled.",
            "examples": [
              null
            ]
          },
          "canceled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the rest was canceled.",
            "examples": [
              null
            ]
          },
          "recipient_count": {
            "type": "integer",
            "description": "How many people it goes to, up to 500."
          },
          "counts": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer"
            },
            "description": "How many recipients are in each state: `pending`, `queued`, `sent`, `delivered`, `read`, `failed`, `skipped` and so on."
          },
          "estimate": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BroadcastEstimate"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a scheduled or sending broadcast, when the rest should go. Worked out on `GET /v1/broadcasts/{id}` and when it is made; null in lists."
          },
          "created_via": {
            "type": "string",
            "enum": [
              "dashboard",
              "api",
              "assistant",
              "mcp",
              "zapier",
              "cli"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "text",
          "text_deleted",
          "template_id",
          "audience",
          "service",
          "state",
          "send_at",
          "started_at",
          "completed_at",
          "canceled_at",
          "recipient_count",
          "counts",
          "estimate",
          "created_via",
          "created_at"
        ],
        "description": "One text to a list of up to 500 people who asked to hear from you, paced by your Mac."
      },
      "BroadcastRecipient": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "broadcast_recipient"
          },
          "contact_id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "handle": {
            "type": "string",
            "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
            "examples": [
              "+15555550123"
            ]
          },
          "name": {
            "description": "The person’s name, when known.",
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "queued",
              "skipped",
              "sent",
              "delivered",
              "read",
              "failed",
              "unconfirmed",
              "expired",
              "canceled"
            ],
            "description": "`pending` until their text is queued, then the text’s own state; `skipped` when they won’t get it."
          },
          "skip_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "stopped",
                  "invalid",
                  "duplicate",
                  "deleted"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "`stopped` (on your stop list), `invalid`, `duplicate` or `deleted`."
          },
          "message_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^msg_[0-9A-Za-z]{22}$",
                "description": "A msg_ id.",
                "examples": [
                  "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "object",
          "contact_id",
          "handle",
          "name",
          "state",
          "skip_reason",
          "message_id"
        ],
        "description": "One person in a broadcast."
      },
      "BroadcastEstimate": {
        "type": "object",
        "properties": {
          "first_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the first text should go.",
            "examples": [
              null
            ]
          },
          "last_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the last text should go, given your pace, quiet hours and daily limits.",
            "examples": [
              null
            ]
          },
          "days": {
            "type": "integer",
            "description": "How many days the sending spans in your time zone."
          },
          "waits_for": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Holds the texts will meet on the way: `quiet_hours`, `daily_new_people_limit`, `platform_daily_limit`."
          },
          "blocked_by": {
            "description": "A hold with no end that stops the broadcast from going, such as `plan_lapsed`.",
            "type": [
              "string",
              "null"
            ]
          },
          "mac_online": {
            "type": "boolean",
            "description": "Whether your Mac is online now. The estimate assumes it stays on."
          }
        },
        "required": [
          "first_at",
          "last_at",
          "days",
          "waits_for",
          "blocked_by",
          "mac_online"
        ],
        "description": "When the broadcast’s texts should go, worked out with your sending rules."
      },
      "BroadcastPreview": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "broadcast_preview"
          },
          "recipient_count": {
            "type": "integer",
            "description": "Everyone it would go to, counting people on your stop list."
          },
          "stopped_count": {
            "type": "integer",
            "description": "People on your stop list, who won’t get it."
          },
          "new_people_count": {
            "type": "integer",
            "description": "People you have never texted, who count toward your daily limit for new people."
          },
          "duplicate_count": {
            "type": "integer",
            "description": "Rows dropped because the same person was already in the list."
          },
          "samples": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "handle": {
                  "type": "string",
                  "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
                  "examples": [
                    "+15555550123"
                  ]
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "text": {
                  "type": "string",
                  "description": "Their text, filled in."
                },
                "missing": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Variables they had no value for, which were left empty."
                }
              },
              "required": [
                "handle",
                "name",
                "text",
                "missing"
              ]
            },
            "description": "The first five people’s texts."
          },
          "estimate": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BroadcastEstimate"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "object",
          "recipient_count",
          "stopped_count",
          "new_people_count",
          "duplicate_count",
          "samples",
          "estimate"
        ],
        "description": "What a broadcast would do: who gets it, the first five texts and when the last should go."
      },
      "Sequence": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^seq_[0-9A-Za-z]{22}$",
            "description": "A seq_ id.",
            "examples": [
              "seq_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "sequence"
          },
          "name": {
            "type": "string",
            "examples": [
              "New lead follow-up"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "archived"
            ],
            "description": "`active` takes new people and sends; `paused` holds every enrollment where it is; `archived` ends them."
          },
          "stop_on_reply": {
            "type": "boolean",
            "description": "Stop a person’s run when they text back. On unless you turn it off. A stop word always stops it."
          },
          "send_window": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "days": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "mon",
                        "tue",
                        "wed",
                        "thu",
                        "fri",
                        "sat",
                        "sun"
                      ]
                    },
                    "description": "The days it may send on."
                  },
                  "start": {
                    "type": "string",
                    "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                    "description": "A time of day as HH:MM in your account’s time zone."
                  },
                  "end": {
                    "type": "string",
                    "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                    "description": "A time of day as HH:MM in your account’s time zone."
                  }
                },
                "required": [
                  "days",
                  "start",
                  "end"
                ],
                "description": "When steps may send, in your time zone. A step due outside it waits for it to open."
              },
              {
                "type": "null"
              }
            ]
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SequenceStep"
            }
          },
          "counts": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Enrollments by state: `active`, `completed`, `stopped`, `canceled`."
          },
          "created_via": {
            "type": "string",
            "enum": [
              "dashboard",
              "api",
              "assistant",
              "mcp",
              "zapier",
              "cli"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "description",
          "state",
          "stop_on_reply",
          "send_window",
          "steps",
          "counts",
          "created_via",
          "created_at"
        ],
        "description": "A run of texts and waits that stops when the person replies or texts STOP."
      },
      "SequenceStep": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^step_[0-9A-Za-z]{22}$",
            "description": "A step_ id.",
            "examples": [
              "step_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "position": {
            "type": "integer",
            "description": "Its place in the sequence, from 0."
          },
          "kind": {
            "type": "string",
            "enum": [
              "text",
              "wait"
            ]
          },
          "wait_seconds": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "For a wait: how long, from a minute to a year."
          },
          "text": {
            "description": "For a text: the words, with `{{variables}}`.",
            "type": [
              "string",
              "null"
            ]
          },
          "template_id": {
            "description": "For a text: the template it uses instead of `text`.",
            "type": [
              "string",
              "null"
            ]
          },
          "service": {
            "type": "string",
            "enum": [
              "auto",
              "imessage",
              "sms"
            ]
          }
        },
        "required": [
          "id",
          "position",
          "kind",
          "wait_seconds",
          "text",
          "template_id",
          "service"
        ],
        "description": "A step: send a text, or wait."
      },
      "Enrollment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^enr_[0-9A-Za-z]{22}$",
            "description": "A enr_ id.",
            "examples": [
              "enr_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "enrollment"
          },
          "sequence_id": {
            "type": "string",
            "pattern": "^seq_[0-9A-Za-z]{22}$",
            "description": "A seq_ id.",
            "examples": [
              "seq_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "contact_id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "handle": {
            "type": "string",
            "description": "A phone number in E.164 (`+15555550123`) or an email address an Apple ID uses (iMessage only).",
            "examples": [
              "+15555550123"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "completed",
              "stopped",
              "canceled"
            ]
          },
          "current_step": {
            "type": "integer",
            "description": "The position of the next step."
          },
          "next_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the next step happens, while active.",
            "examples": [
              null
            ]
          },
          "stop_reason": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "replied",
                  "stopped",
                  "canceled",
                  "sequence_archived",
                  "failed"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Why it ended early, when it did."
          },
          "enrolled_via": {
            "type": "string",
            "enum": [
              "dashboard",
              "api",
              "zapier",
              "make",
              "n8n",
              "pipedream",
              "cli",
              "hook",
              "keyword",
              "mcp",
              "assistant",
              "widget"
            ]
          },
          "variables": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "type": "string"
            },
            "description": "Values for the steps’ `{{variables}}`."
          },
          "enrolled_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the person was added.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it ended, by finishing or stopping.",
            "examples": [
              null
            ]
          },
          "timeline": {
            "description": "What happened, oldest first. Only on `GET /v1/enrollments/{id}`.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "enrolled",
                    "text_queued",
                    "text_skipped",
                    "waiting",
                    "window",
                    "stopped",
                    "completed",
                    "canceled"
                  ]
                },
                "position": {
                  "anyOf": [
                    {
                      "type": "integer"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "description": "The step it is about."
                },
                "message_id": {
                  "anyOf": [
                    {
                      "type": "string",
                      "pattern": "^msg_[0-9A-Za-z]{22}$",
                      "description": "A msg_ id.",
                      "examples": [
                        "msg_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "until": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time"
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "description": "For a wait, when it ends.",
                  "examples": [
                    null
                  ]
                },
                "detail": {
                  "description": "What happened, in words.",
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When.",
                  "examples": [
                    "2026-11-13T19:41:00.000Z"
                  ]
                }
              },
              "required": [
                "type",
                "position",
                "message_id",
                "until",
                "detail",
                "at"
              ]
            }
          }
        },
        "required": [
          "id",
          "object",
          "sequence_id",
          "contact_id",
          "handle",
          "state",
          "current_step",
          "next_run_at",
          "stop_reason",
          "enrolled_via",
          "variables",
          "enrolled_at",
          "completed_at"
        ],
        "description": "A person’s run through a sequence."
      },
      "TextHook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^hook_[0-9A-Za-z]{22}$",
            "description": "A hook_ id.",
            "examples": [
              "hook_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "text_hook"
          },
          "name": {
            "type": "string",
            "examples": [
              "Calendly bookings"
            ]
          },
          "url": {
            "type": "string",
            "description": "The address to post to. Anyone with it can send texts from your number, so keep it private.",
            "examples": [
              "https://usebluebot.com/h/th_8Rk2mQ4zN7wX1cVbL5pT9yHs"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "test_mode": {
            "type": "boolean",
            "description": "Posts are recorded and checked but no text is sent."
          },
          "mapping": {
            "type": "object",
            "properties": {
              "to": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 200
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Who to text, as a `{{body.…}}` path into the posted fields.",
                "examples": [
                  "{{body.phone}}"
                ]
              },
              "text": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 2000
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "The words, with `{{body.…}}` fields. Leave it empty to use `template_id`."
              },
              "first_name": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 200
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Saved on the contact when it has no first name yet."
              },
              "last_name": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 200
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "tags": {
                "anyOf": [
                  {
                    "type": "string",
                    "maxLength": 200
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Tags to add, separated by commas. May use `{{body.…}}` fields."
              }
            },
            "required": [
              "to",
              "text",
              "first_name",
              "last_name",
              "tags"
            ],
            "description": "How a post becomes a text. Each value is a template over the posted fields: `body` for the JSON or form, `query` for the address’s query string."
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "sequence_id": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^seq_[0-9A-Za-z]{22}$",
                "description": "A seq_ id.",
                "examples": [
                  "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "A sequence each person is added to."
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it last received a post.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "url",
          "enabled",
          "test_mode",
          "mapping",
          "template_id",
          "sequence_id",
          "last_used_at",
          "created_at"
        ],
        "description": "An address that turns any app’s webhook post into a text from your number."
      },
      "KeywordRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^kw_[0-9A-Za-z]{22}$",
            "description": "A kw_ id.",
            "examples": [
              "kw_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "object": {
            "type": "string",
            "const": "keyword_rule"
          },
          "name": {
            "type": "string",
            "examples": [
              "Hours"
            ]
          },
          "match": {
            "type": "string",
            "enum": [
              "exact",
              "starts_with",
              "word",
              "contains",
              "regex"
            ],
            "description": "`exact` (the whole text), `starts_with`, `word` (a whole word anywhere), `contains`, or `regex`."
          },
          "keywords": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "examples": [
              [
                "hours",
                "open"
              ]
            ]
          },
          "pattern": {
            "description": "For `regex`.",
            "type": [
              "string",
              "null"
            ]
          },
          "case_sensitive": {
            "type": "boolean"
          },
          "actions": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "reply"
                    },
                    "text": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "template_id": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "text",
                    "template_id"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "tag"
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "type",
                    "tags"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "enroll"
                    },
                    "sequence_id": {
                      "type": "string",
                      "pattern": "^seq_[0-9A-Za-z]{22}$",
                      "description": "A seq_ id.",
                      "examples": [
                        "seq_1Hq2LxW9cVbN3mKpRtYs0a"
                      ]
                    }
                  },
                  "required": [
                    "type",
                    "sequence_id"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string",
                      "const": "webhook"
                    }
                  },
                  "required": [
                    "type"
                  ]
                }
              ],
              "description": "What a match does: reply with words or a template, tag the person, add them to a sequence, or send an `automation.matched` webhook event."
            }
          },
          "position": {
            "type": "integer",
            "description": "Rules are tried from the lowest position up; the first match wins."
          },
          "enabled": {
            "type": "boolean"
          },
          "fire_count": {
            "type": "integer",
            "description": "How many texts it answered."
          },
          "last_fired_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "When it last matched.",
            "examples": [
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it was made.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "id",
          "object",
          "name",
          "match",
          "keywords",
          "pattern",
          "case_sensitive",
          "actions",
          "position",
          "enabled",
          "fire_count",
          "last_fired_at",
          "created_at"
        ],
        "description": "A keyword auto-reply. It never fires on a stop word: those stop the person and nothing else."
      },
      "AwayMessage": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "away_message"
          },
          "enabled": {
            "type": "boolean"
          },
          "text": {
            "description": "The reply, with `{{variables}}`.",
            "examples": [
              "Thanks for your text! We’re closed right now and will reply when we open at 9 AM."
            ],
            "type": [
              "string",
              "null"
            ]
          },
          "cooldown_hours": {
            "type": "integer",
            "description": "Each person gets it at most once in this many hours."
          },
          "business_hours": {
            "type": "object",
            "properties": {
              "mon": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "tue": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "wed": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "thu": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "fri": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sat": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sun": {
                "anyOf": [
                  {
                    "type": "object",
                    "properties": {
                      "start": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      },
                      "end": {
                        "type": "string",
                        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$|^24:00$",
                        "description": "A time of day as HH:MM in your account’s time zone."
                      }
                    },
                    "required": [
                      "start",
                      "end"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "mon",
              "tue",
              "wed",
              "thu",
              "fri",
              "sat",
              "sun"
            ],
            "description": "Your hours each day in your time zone; null for a day you’re closed."
          },
          "time_zone": {
            "type": "string",
            "examples": [
              "America/Chicago"
            ]
          },
          "open_now": {
            "type": "boolean",
            "description": "Whether it’s inside your business hours right now."
          }
        },
        "required": [
          "object",
          "enabled",
          "text",
          "cooldown_hours",
          "business_hours",
          "time_zone",
          "open_now"
        ],
        "description": "A reply sent outside your business hours, once per person per `cooldown_hours`."
      },
      "AutomationMatch": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "const": "automation_match"
          },
          "rule_id": {
            "type": "string",
            "pattern": "^kw_[0-9A-Za-z]{22}$",
            "description": "A kw_ id.",
            "examples": [
              "kw_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "rule_name": {
            "type": "string"
          },
          "contact_id": {
            "type": "string",
            "pattern": "^ct_[0-9A-Za-z]{22}$",
            "description": "A ct_ id.",
            "examples": [
              "ct_1Hq2LxW9cVbN3mKpRtYs0a"
            ]
          },
          "actions": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "reply",
                "tag",
                "enroll",
                "webhook"
              ]
            },
            "description": "The rule’s actions, in order."
          },
          "message": {
            "description": "The incoming text that matched.",
            "$ref": "#/components/schemas/Message"
          },
          "matched_at": {
            "type": "string",
            "format": "date-time",
            "description": "When it matched.",
            "examples": [
              "2026-11-13T19:41:00.000Z"
            ]
          }
        },
        "required": [
          "object",
          "rule_id",
          "rule_name",
          "contact_id",
          "actions",
          "message",
          "matched_at"
        ],
        "description": "A keyword rule matched an incoming text."
      },
      "Error": {
        "type": "object",
        "description": "Every refusal has this shape. `code` is stable for programs; `message` is for people.",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "invalid_request",
                  "unauthorized",
                  "plan_lapsed",
                  "forbidden",
                  "insufficient_scope",
                  "account_held",
                  "not_found",
                  "conflict",
                  "idempotency_conflict",
                  "limit_reached",
                  "payload_too_large",
                  "unsupported_media_type",
                  "rate_limited",
                  "internal",
                  "upstream_failed",
                  "unavailable"
                ],
                "description": "Stable, snake_case. Each code has a page at `doc_url`."
              },
              "message": {
                "type": "string",
                "description": "What went wrong, in a sentence."
              },
              "hint": {
                "type": "string",
                "description": "What to do next."
              },
              "doc_url": {
                "type": "string",
                "format": "uri"
              },
              "retry_after": {
                "type": "integer",
                "description": "Seconds to wait, on `rate_limited`."
              },
              "details": {
                "type": "array",
                "description": "For `invalid_request`, each field that didn’t fit.",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "field",
                    "message"
                  ]
                }
              },
              "request_id": {
                "type": "string",
                "description": "Quote it when writing to support."
              }
            },
            "required": [
              "code",
              "message",
              "hint",
              "doc_url",
              "request_id"
            ]
          }
        },
        "required": [
          "error"
        ]
      }
    }
  },
  "x-error-codes": [
    {
      "code": "invalid_request",
      "status": 400,
      "title": "Invalid request",
      "description": "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.",
      "hint": "Check the fields named in the message and send it again.",
      "doc_url": "https://usebluebot.com/docs/errors/invalid_request"
    },
    {
      "code": "unauthorized",
      "status": 401,
      "title": "Unauthorized",
      "description": "The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API.",
      "hint": "Send a valid key as `Authorization: Bearer <key>`.",
      "doc_url": "https://usebluebot.com/docs/errors/unauthorized"
    },
    {
      "code": "plan_lapsed",
      "status": 402,
      "title": "Plan lapsed",
      "description": "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.",
      "hint": "Update the card on the Billing page; texts wait until the plan is active.",
      "doc_url": "https://usebluebot.com/docs/errors/plan_lapsed"
    },
    {
      "code": "forbidden",
      "status": 403,
      "title": "Forbidden",
      "description": "The key is valid but may not do this.",
      "hint": "This key or sign-in may not do that.",
      "doc_url": "https://usebluebot.com/docs/errors/forbidden"
    },
    {
      "code": "insufficient_scope",
      "status": 403,
      "title": "Insufficient scope",
      "description": "The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope.",
      "hint": "Make a key with the scope named in the message.",
      "doc_url": "https://usebluebot.com/docs/errors/insufficient_scope"
    },
    {
      "code": "account_held",
      "status": 403,
      "title": "Account held",
      "description": "BlueBot paused sending on this account, usually while it looks into reports of unwanted texts. Texts are accepted and wait. Write to support@usebluebot.com.",
      "hint": "BlueBot paused this account's sending. Write to support@usebluebot.com.",
      "doc_url": "https://usebluebot.com/docs/errors/account_held"
    },
    {
      "code": "not_found",
      "status": 404,
      "title": "Not found",
      "description": "There is no such thing on this account. Ids are prefixed by kind, so a message id starts with `msg_`.",
      "hint": "Check the id. Ids are prefixed by kind, such as `msg_` for a message.",
      "doc_url": "https://usebluebot.com/docs/errors/not_found"
    },
    {
      "code": "conflict",
      "status": 409,
      "title": "Conflict",
      "description": "The request doesn’t fit the thing’s current state, or another request with the same Idempotency-Key is still running.",
      "hint": "Read the current state and try again.",
      "doc_url": "https://usebluebot.com/docs/errors/conflict"
    },
    {
      "code": "idempotency_conflict",
      "status": 409,
      "title": "Idempotency key reused",
      "description": "The Idempotency-Key was used in the last 24 hours with a different request. A key stands for one request.",
      "hint": "This Idempotency-Key was used in the last 24 hours with a different request. Use a new key for a new request.",
      "doc_url": "https://usebluebot.com/docs/errors/idempotency_conflict"
    },
    {
      "code": "limit_reached",
      "status": 409,
      "title": "Limit reached",
      "description": "The account has as many of something as it may have.",
      "hint": "You have reached a limit on your account. The docs list each limit.",
      "doc_url": "https://usebluebot.com/docs/errors/limit_reached"
    },
    {
      "code": "payload_too_large",
      "status": 413,
      "title": "Payload too large",
      "description": "The request is bigger than the endpoint takes.",
      "hint": "Send less. The docs list each size limit.",
      "doc_url": "https://usebluebot.com/docs/errors/payload_too_large"
    },
    {
      "code": "unsupported_media_type",
      "status": 415,
      "title": "Unsupported media type",
      "description": "The body isn’t a type the endpoint reads: JSON for most, a multipart form for file uploads, and only the file types listed for files.",
      "hint": "Send `Content-Type: application/json`.",
      "doc_url": "https://usebluebot.com/docs/errors/unsupported_media_type"
    },
    {
      "code": "rate_limited",
      "status": 429,
      "title": "Rate limited",
      "description": "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.",
      "hint": "Wait the number of seconds in `retry_after`, then try again.",
      "doc_url": "https://usebluebot.com/docs/errors/rate_limited"
    },
    {
      "code": "internal",
      "status": 500,
      "title": "Internal error",
      "description": "Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe.",
      "hint": "Try again. If it keeps happening, write to support with the request_id.",
      "doc_url": "https://usebluebot.com/docs/errors/internal"
    },
    {
      "code": "upstream_failed",
      "status": 502,
      "title": "Upstream failed",
      "description": "A service BlueBot depends on failed.",
      "hint": "A service BlueBot depends on failed. Try again shortly.",
      "doc_url": "https://usebluebot.com/docs/errors/upstream_failed"
    },
    {
      "code": "unavailable",
      "status": 503,
      "title": "Unavailable",
      "description": "BlueBot isn’t taking requests right now, during maintenance or an incident. `GET /v1/status` says what is going on.",
      "hint": "BlueBot is not taking requests right now. Try again shortly.",
      "doc_url": "https://usebluebot.com/docs/errors/unavailable"
    }
  ],
  "x-event-types": [
    "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"
  ]
}
