{
  "openapi": "3.1.0",
  "info": {
    "title": "BirdyChat Integrations API",
    "version": "v1",
    "x-changelog-url": "https://docs.birdy.chat/changelog",
    "x-deprecation-policy-url": "https://docs.birdy.chat/deprecation-policy",
    "description": "Public OpenAPI document for the BirdyChat integrations REST API.\n\nCreate an integration:\n- In BirdyChat, open the account menu and choose Integrations, or open the [Integrations page](https://birdy.chat/web/integrations).\n- After creating it, use the generated token with this API or the BirdyChat MCP server.\n\nAuthentication:\n- Use `Authorization: Bearer sk_...` for every request.\n\nReliability:\n- Use the `Idempotency-Key` request header to deduplicate requests.\n- REST API is limited to 500 requests per minute. This limit is shared across endpoints and not yet operation-specific.\n\nErrors:\n- All error responses use a consistent error envelope schema.\n- Inspect both HTTP status and `error.code` for handling logic.\n- Examples of currently documented machine-readable error codes include:\n  `forbidden`, `invalid_channel_id`, `invalid_json`, `invalid_message`,\n  `invalid_message_id`, `invalid_params`, `invalid_thread_id`, `missing_message`, `missing_thread_id`,\n  `not_authenticated`, `not_found`, and `permission_denied`.\n\nWebhooks:\n- Webhook events are signed using `x-birdy-signature`.\n- Verify signatures before processing payloads.\n\nAI tools:\n- For an LLM-friendly summary, see https://docs.birdy.chat/llms.txt.\n- For the canonical contract, use https://docs.birdy.chat/openapi.json or https://docs.birdy.chat/openapi.yaml.\n"
  },
  "servers": [
    {
      "url": "https://birdy.chat/api/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Threads",
      "description": "Thread resources and related operations."
    },
    {
      "name": "Messages",
      "description": "Message resources and related operations."
    },
    {
      "name": "Channels",
      "description": "Channel resources and related operations."
    },
    {
      "name": "Attachments",
      "description": "Attachment resources and related operations."
    },
    {
      "name": "Users",
      "description": "User resources and related operations."
    },
    {
      "name": "Scheduled Messages",
      "description": "Scheduled message resources and related operations."
    },
    {
      "name": "Events",
      "description": "Canonical events stream resources."
    },
    {
      "name": "Webhooks",
      "description": "Outbound webhook events for integrations."
    },
    {
      "name": "Integrations",
      "description": "Manage integrations (personal tokens and bots) created by the user."
    }
  ],
  "paths": {
    "/threads": {
      "get": {
        "tags": [
          "Threads"
        ],
        "operationId": "listThreads",
        "summary": "List threads",
        "description": "Lists threads from the authenticated integration bot inbox by default.\nResults are ordered by `last_message_created_at` (descending). For empty threads,\n`last_message_created_at` matches the thread creation timestamp.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/threads?limit=20\" \\\n  -H \"Authorization: Bearer sk_...\"\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://birdy.chat/api/v1/threads\",\n    headers={\"Authorization\": \"Bearer sk_...\"},\n    params={\"limit\": 20},\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/threads?limit=20\", {\n  headers: { Authorization: \"Bearer sk_...\" }\n});\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelId"
          },
          {
            "$ref": "#/components/parameters/ParentThreadId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/BeforeId"
          }
        ],
        "responses": {
          "200": {
            "description": "Thread list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadListResponse"
                },
                "examples": {
                  "success": {
                    "summary": "Threads in inbox/channel",
                    "value": {
                      "data": [
                        {
                          "id": "th_fmn8SsKHoavown2s",
                          "object": "thread",
                          "name": "Customer onboarding",
                          "description": null,
                          "last_message_excerpt": "Initial import message",
                          "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                          "last_author_ids": [
                            "u_tgJfNUiC1nDV4"
                          ],
                          "last_message_created_at": "2026-02-18T10:03:57.277962Z",
                          "user_ids": [
                            "u_tgJfNUiC1nDV4",
                            "u_zLqW4mDNJBHc2"
                          ],
                          "users": [
                            {
                              "user_id": "u_tgJfNUiC1nDV4",
                              "roles": [
                                "creator",
                                "owner"
                              ]
                            },
                            {
                              "user_id": "u_zLqW4mDNJBHc2",
                              "roles": []
                            }
                          ],
                          "users_count": 2,
                          "read_receipts": {
                            "u_tgJfNUiC1nDV4": {
                              "message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                              "read_at": "2026-02-18T10:03:57.277962Z"
                            }
                          },
                          "settings": {
                            "is_sharing_enabled": false
                          },
                          "share_link": null,
                          "parent_thread_id": null,
                          "parent_message_id": null,
                          "created_at": "2026-02-18T10:03:57.277962Z",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        },
                        {
                          "id": "th_pK3xHwR8nLb2vYqA",
                          "object": "thread",
                          "name": "One-on-one",
                          "description": null,
                          "one_on_one_user_id_pair": "u_tgJfNUiC1nDV4,u_zLqW4mDNJBHc2",
                          "last_message_excerpt": "Thanks Alice. Can you share the URL and a screenshot?",
                          "last_message_id": "m_032Kw5BC3EWyjHk83UydbF",
                          "last_author_ids": [
                            "u_zLqW4mDNJBHc2"
                          ],
                          "last_message_created_at": "2026-02-18T10:04:15.277962Z",
                          "user_ids": [
                            "u_tgJfNUiC1nDV4",
                            "u_zLqW4mDNJBHc2"
                          ],
                          "users": [
                            {
                              "user_id": "u_tgJfNUiC1nDV4",
                              "roles": [
                                "creator",
                                "owner"
                              ]
                            },
                            {
                              "user_id": "u_zLqW4mDNJBHc2",
                              "roles": []
                            }
                          ],
                          "users_count": 2,
                          "read_receipts": {
                            "u_tgJfNUiC1nDV4": {
                              "message_id": "m_032Kw5BC3EWyjHk83UydbF",
                              "read_at": "2026-02-18T10:04:15.277962Z"
                            }
                          },
                          "settings": {
                            "is_sharing_enabled": false
                          },
                          "share_link": null,
                          "parent_thread_id": null,
                          "parent_message_id": null,
                          "created_at": "2026-02-18T10:03:57.277962Z",
                          "updated_at": "2026-02-18T10:04:15.277962Z"
                        }
                      ],
                      "object": "list",
                      "has_more": false,
                      "next_cursor": null,
                      "prev_cursor": null
                    }
                  },
                  "subThreads": {
                    "summary": "Sub-threads of a parent thread",
                    "value": {
                      "data": [
                        {
                          "id": "th_9xKpQ3mRvNwT2hYs",
                          "object": "thread",
                          "name": "Check out https://example.com/page",
                          "description": null,
                          "last_message_excerpt": "Replying in a sub-thread",
                          "last_message_id": "m_7nWx5KpR2mTvQhYs",
                          "last_author_ids": [
                            "u_tgJfNUiC1nDV4"
                          ],
                          "last_message_created_at": "2026-02-18T10:05:00.000000Z",
                          "user_ids": [],
                          "users": [],
                          "users_count": 0,
                          "read_receipts": {
                            "u_tgJfNUiC1nDV4": {
                              "message_id": "m_7nWx5KpR2mTvQhYs",
                              "read_at": "2026-02-18T10:05:01.000000Z"
                            }
                          },
                          "settings": {
                            "is_sharing_enabled": false
                          },
                          "share_link": null,
                          "parent_thread_id": "th_fmn8SsKHoavown2s",
                          "parent_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                          "joined": true,
                          "created_at": "2026-02-18T10:05:00.000000Z",
                          "updated_at": "2026-02-18T10:05:00.000000Z"
                        }
                      ],
                      "object": "list",
                      "has_more": false,
                      "next_cursor": null,
                      "prev_cursor": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "createThread",
        "summary": "Create thread",
        "description": "Creates a thread and posts the first message.\n\n**Regular thread:** supply `recipient_emails` (and optionally `thread.name`).\nIf a recipient email does not yet exist, the flow may create/invite that user.\n\n**Sub-thread:** supply `parent_thread_id` and `parent_message_id` instead of\n`recipient_emails`. The sub-thread is created off the given parent message.\n\nUse the `Idempotency-Key` request header to deduplicate requests.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/threads\" \\\n  -H \"Authorization: Bearer sk_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"recipient_emails\": [\"alice.finch@example.com\"],\n    \"thread\": { \"name\": \"Customer onboarding\" },\n    \"message\": { \"body\": \"Initial sync from external system\" }\n  }'\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\npayload = {\n    \"recipient_emails\": [\"alice.finch@example.com\"],\n    \"thread\": {\"name\": \"Customer onboarding\"},\n    \"message\": {\"body\": \"Initial sync from external system\"},\n}\n\nresponse = requests.post(\n    \"https://birdy.chat/api/v1/threads\",\n    headers={\n        \"Authorization\": \"Bearer sk_...\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=payload,\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/threads\", {\n  method: \"POST\",\n  headers: {\n    Authorization: \"Bearer sk_...\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    recipient_emails: [\"alice.finch@example.com\"],\n    thread: { name: \"Customer onboarding\" },\n    message: { body: \"Initial sync from external system\" },\n  }),\n});\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadCreateRequest"
              },
              "examples": {
                "default": {
                  "summary": "Create a regular thread",
                  "value": {
                    "recipient_emails": [
                      "alice.finch@example.com"
                    ],
                    "thread": {
                      "name": "Customer onboarding"
                    },
                    "message": {
                      "body": "Initial sync from external system"
                    }
                  }
                },
                "oneOnOne": {
                  "summary": "Create a one-on-one thread",
                  "value": {
                    "recipient_emails": [
                      "alice.finch@example.com"
                    ],
                    "thread": {},
                    "message": {
                      "body": "Thanks Alice. Can you share the URL and a screenshot? I'll also check our auth logs on this end."
                    }
                  }
                },
                "subThread": {
                  "summary": "Create a sub-thread off a parent message",
                  "value": {
                    "parent_thread_id": "th_fmn8SsKHoavown2s",
                    "parent_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                    "message": {
                      "body": "Replying in a sub-thread"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Thread and first message were created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadCreateResponse"
                },
                "examples": {
                  "success": {
                    "summary": "Regular thread created",
                    "value": {
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Initial sync from external system",
                        "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "last_author_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "last_message_created_at": "2026-02-18T10:03:58.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "read_receipts": {
                          "u_tgJfNUiC1nDV4": {
                            "message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                            "read_at": "2026-02-18T10:03:57.277962Z"
                          }
                        },
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "share_link": null,
                        "parent_thread_id": null,
                        "parent_message_id": null,
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:03:57.277962Z",
                        "idempotency_key": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
                      },
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "body": "Initial sync from external system",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:03:58.277962Z"
                      },
                      "thread_in_channels": [
                        {
                          "channel_id": "ch_DNb4kFmRhJp9wT",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "present",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        }
                      ]
                    }
                  },
                  "subThread": {
                    "summary": "Sub-thread created",
                    "value": {
                      "thread": {
                        "id": "th_9xKpQ3mRvNwT2hYs",
                        "object": "thread",
                        "name": "Check out https://example.com/page",
                        "description": null,
                        "last_message_excerpt": "Replying in a sub-thread",
                        "last_message_id": "m_7nWx5KpR2mTvQhYs",
                        "last_author_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "last_message_created_at": "2026-02-18T10:05:00.000000Z",
                        "user_ids": [],
                        "users": [],
                        "users_count": 0,
                        "read_receipts": {},
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "share_link": null,
                        "parent_thread_id": "th_fmn8SsKHoavown2s",
                        "parent_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "joined": true,
                        "created_at": "2026-02-18T10:05:00.000000Z",
                        "updated_at": "2026-02-18T10:05:00.000000Z"
                      },
                      "message": {
                        "id": "m_7nWx5KpR2mTvQhYs",
                        "object": "message",
                        "thread_id": "th_9xKpQ3mRvNwT2hYs",
                        "body": "Replying in a sub-thread",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:05:00.000000Z"
                      },
                      "parent_message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "body": "Follow-up from external system",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": "th_9xKpQ3mRvNwT2hYs",
                        "created_at": "2026-02-18T10:03:58.277962Z",
                        "updated_at": "2026-02-18T10:05:00.000000Z"
                      },
                      "threads_in_channels": [
                        {
                          "channel_id": "ch_DNb4kFmRhJp9wT",
                          "thread_id": "th_9xKpQ3mRvNwT2hYs",
                          "status": "present",
                          "updated_at": "2026-02-18T10:05:00.000000Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "description": "A sub-thread already exists for this parent message.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "subThreadExists": {
                    "value": {
                      "error": {
                        "type": "conflict",
                        "code": "sub_thread_already_exists",
                        "message": "Can't create sub-thread",
                        "description": "A sub-thread already exists for this message",
                        "thread_id": "th_9xKpQ3mRvNwT2hYs"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/archive": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "archiveThreads",
        "summary": "Archive threads",
        "description": "Archives one or more threads for the current user.\n`last_message_ids` must include one entry per `thread_id`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadArchiveRequest"
              },
              "examples": {
                "archiveMany": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "last_message_ids": [
                      {
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                      }
                    ],
                    "archived_at": "2026-02-18T10:03:57.277962Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Threads were archived.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadArchiveResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread_ids": [
                        "th_fmn8SsKHoavown2s"
                      ],
                      "thread_in_channels": [
                        {
                          "channel_id": "ch_7sUNVzywAU8CGi",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "present",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        },
                        {
                          "channel_id": "ch_DNb4kFmRhJp9wT",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "absent",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/snooze": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "snoozeThreads",
        "summary": "Snooze threads",
        "description": "Snoozes one or more threads until the provided datetime.\n`last_message_ids` must include one entry per `thread_id`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadSnoozeRequest"
              },
              "examples": {
                "snoozeMany": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "snoozed_until": "2026-02-18T10:05:10.277962Z",
                    "last_message_ids": [
                      {
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                      }
                    ],
                    "snoozed_at": "2026-02-18T10:03:57.277962Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Threads were snoozed.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadSnoozeResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "snoozed_thread_ids": [
                        "th_fmn8SsKHoavown2s"
                      ],
                      "thread_in_channels": [
                        {
                          "channel_id": "ch_DNb4kFmRhJp9wT",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "present",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        },
                        {
                          "channel_id": "ch_7sUNVzywAU8CGi",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "absent",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/mute": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "muteThreads",
        "summary": "Mute or unmute threads",
        "description": "Mutes or unmutes one or more threads.\nSet `muted_until` to a datetime, `\"forever\"`, or `null` (to unmute).\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadMuteRequest"
              },
              "examples": {
                "muteUntil": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "muted_until": "2026-02-18T11:14:33.277962Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Threads were muted/unmuted.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadMuteResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread_ids": [
                        "th_fmn8SsKHoavown2s"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/move": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "moveThreads",
        "summary": "Move threads between channels",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadMoveRequest"
              },
              "examples": {
                "moveMany": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "from_channel_id": "ch_DNb4kFmRhJp9wT",
                    "to_channel_id": "ch_7sUNVzywAU8CGi",
                    "moved_at": "2026-02-18T10:03:57.277962Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Threads were moved.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadMoveResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread_ids": [
                        "th_fmn8SsKHoavown2s"
                      ],
                      "thread_in_channels": [
                        {
                          "channel_id": "ch_7sUNVzywAU8CGi",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "present",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        },
                        {
                          "channel_id": "ch_DNb4kFmRhJp9wT",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "status": "absent",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}": {
      "get": {
        "tags": [
          "Threads"
        ],
        "operationId": "getThread",
        "summary": "Retrieve thread",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Thread object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Thread"
                },
                "examples": {
                  "success": {
                    "value": {
                      "id": "th_fmn8SsKHoavown2s",
                      "object": "thread",
                      "name": "Customer onboarding",
                      "description": null,
                      "last_message_excerpt": "Initial sync from external system",
                      "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                      "last_author_ids": [
                        "u_tgJfNUiC1nDV4"
                      ],
                      "last_message_created_at": "2026-02-18T10:03:58.277962Z",
                      "user_ids": [
                        "u_tgJfNUiC1nDV4",
                        "u_zLqW4mDNJBHc2"
                      ],
                      "users": [
                        {
                          "user_id": "u_tgJfNUiC1nDV4",
                          "roles": [
                            "creator",
                            "owner"
                          ]
                        },
                        {
                          "user_id": "u_zLqW4mDNJBHc2",
                          "roles": []
                        }
                      ],
                      "users_count": 2,
                      "read_receipts": {
                        "u_tgJfNUiC1nDV4": {
                          "message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                          "read_at": "2026-02-18T10:03:57.277962Z"
                        }
                      },
                      "settings": {
                        "is_sharing_enabled": false
                      },
                      "share_link": null,
                      "created_at": "2026-02-18T10:03:57.277962Z",
                      "updated_at": "2026-02-18T10:03:57.277962Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/threads/read": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "readThreads",
        "summary": "Mark threads as read or unread (bulk)",
        "description": "Stores read receipts for the current user in one or more threads.\n`message_ids` must include one entry per `thread_id`.\nPass `message_id: null` in an entry to mark that thread as unread.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadReadRequest"
              },
              "examples": {
                "readMany": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "message_ids": [
                      {
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                      }
                    ]
                  }
                },
                "unreadMany": {
                  "value": {
                    "thread_ids": [
                      "th_fmn8SsKHoavown2s"
                    ],
                    "message_ids": [
                      {
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "message_id": null
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Read receipts were updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadReadResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "threads": [
                        {
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/mark_read": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "markThreadRead",
        "summary": "Mark thread as read (or unread)",
        "description": "Stores read receipt for the current user in the thread.\nPass `message_id: null` to mark as unread.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadMarkReadRequest"
              },
              "examples": {
                "markRead": {
                  "value": {
                    "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                  }
                },
                "markUnread": {
                  "value": {
                    "message_id": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Read receipt was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadMarkReadResponse"
                },
                "examples": {
                  "read": {
                    "value": {
                      "thread_id": "th_fmn8SsKHoavown2s",
                      "message_id": "m_032Kw4XA2DVxiGj72TxcaE"
                    }
                  },
                  "unread": {
                    "value": {
                      "thread_id": "th_fmn8SsKHoavown2s",
                      "message_id": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/users": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "addThreadUsers",
        "summary": "Add users to thread",
        "description": "Adds users by email and returns the updated thread object.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadAddUsersRequest"
              },
              "examples": {
                "addByEmail": {
                  "value": {
                    "emails": [
                      "alice.finch@example.com"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Users were added.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadUsersMutationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      },
      "delete": {
        "tags": [
          "Threads"
        ],
        "operationId": "removeThreadUsers",
        "summary": "Remove users from thread",
        "description": "Removes users by prefixed user ids and returns the updated thread object.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadRemoveUsersRequest"
              },
              "examples": {
                "removeById": {
                  "value": {
                    "user_ids": [
                      "u_zLqW4mDNJBHc2"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Users were removed.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadUsersMutationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/users/roles/{role}": {
      "post": {
        "tags": [
          "Threads"
        ],
        "operationId": "addThreadUserRole",
        "summary": "Add role for users in thread",
        "description": "Grants a role to the provided users in the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/Role"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadRoleMutationRequest"
              },
              "examples": {
                "addOwner": {
                  "value": {
                    "user_ids": [
                      "u_zLqW4mDNJBHc2"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role was added for users.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadUsersMutationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "users": [
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": [
                              "owner"
                            ]
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      },
      "delete": {
        "tags": [
          "Threads"
        ],
        "operationId": "removeThreadUserRole",
        "summary": "Remove role for users in thread",
        "description": "Revokes a role from the provided users in the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/Role"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadRoleMutationRequest"
              },
              "examples": {
                "removeOwner": {
                  "value": {
                    "user_ids": [
                      "u_zLqW4mDNJBHc2"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role was removed for users.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadUsersMutationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "users": [
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/messages": {
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "listThreadMessages",
        "summary": "List messages in thread",
        "description": "Preferred endpoint for fetching messages scoped to a thread.\nSupports pagination via `limit` and `before_id` (message cursor).\nReturns `400` when the `thread_id` is malformed.\nReturns `404` when the thread is not accessible to the authenticated integration user.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages?limit=20\" \\\n  -H \"Authorization: Bearer sk_...\"\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages\",\n    headers={\"Authorization\": \"Bearer sk_...\"},\n    params={\"limit\": 20},\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\n  \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages?limit=20\",\n  { headers: { Authorization: \"Bearer sk_...\" } }\n);\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/BeforeId"
          }
        ],
        "responses": {
          "200": {
            "description": "Message list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageListResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "data": [
                        {
                          "id": "m_032Kw4XA2DVxiGj72TxcaE",
                          "object": "message",
                          "thread_id": "th_fmn8SsKHoavown2s",
                          "user_id": "u_tgJfNUiC1nDV4",
                          "body": "Follow-up from external system",
                          "reply_to_message_excerpt": null,
                          "sub_thread_id": null,
                          "created_at": "2026-02-18T10:04:15.277962Z"
                        }
                      ],
                      "object": "list",
                      "has_more": false,
                      "next_cursor": null,
                      "prev_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "createThreadMessage",
        "summary": "Create message in thread",
        "description": "Preferred endpoint for creating a message in a specific thread.\nThe authenticated integration user must be a thread participant.\nReturns `400` when the `thread_id` is malformed or when both `body` and `attachments` are missing.\n\nAlso works with sub-thread IDs — once a sub-thread is created via\n`POST /threads`, use this endpoint to post follow-up messages into it.\n\nUse the `Idempotency-Key` request header to deduplicate requests.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages\" \\\n  -H \"Authorization: Bearer sk_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: cb25dfd0-add8-4e90-81c1-1a07e3581dfa\" \\\n  -d '{\"message\": {\"body\": \"Follow-up from external system\"}}'\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\npayload = {\"message\": {\"body\": \"Follow-up from external system\"}}\n\nresponse = requests.post(\n    \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages\",\n    headers={\n        \"Authorization\": \"Bearer sk_...\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": \"cb25dfd0-add8-4e90-81c1-1a07e3581dfa\",\n    },\n    json=payload,\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\n  \"https://birdy.chat/api/v1/threads/th_fmn8SsKHoavown2s/messages\",\n  {\n    method: \"POST\",\n    headers: {\n      Authorization: \"Bearer sk_...\",\n      \"Content-Type\": \"application/json\",\n    },\n    body: JSON.stringify({\n      message: { body: \"Follow-up from external system\" },\n    }),\n  }\n);\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadMessageCreateRequest"
              },
              "examples": {
                "default": {
                  "summary": "Post into a thread",
                  "value": {
                    "message": {
                      "body": "Follow-up from external system"
                    }
                  }
                },
                "subThread": {
                  "summary": "Post into a sub-thread",
                  "value": {
                    "message": {
                      "body": "Follow-up in the sub-thread"
                    }
                  }
                },
                "withAttachments": {
                  "summary": "Message with attachments",
                  "value": {
                    "message": {
                      "body": "See attached screenshot",
                      "attachments": [
                        {
                          "id": "att_DT7QcSFMRe5mlz"
                        }
                      ]
                    }
                  }
                },
                "attachmentOnly": {
                  "summary": "Attachment-only message (no body)",
                  "value": {
                    "message": {
                      "attachments": [
                        {
                          "id": "att_DT7QcSFMRe5mlz"
                        }
                      ]
                    }
                  }
                },
                "reply": {
                  "summary": "Threaded reply",
                  "value": {
                    "message": {
                      "body": "Thanks Alice. Can you share the URL and a screenshot? I'll also check our auth logs on this end.",
                      "reply_to": "m_032Kw4XA2DVxiGj72TxcaE"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message was created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageCreateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "body": "Follow-up from external system",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:04:15.277962Z",
                        "idempotency_key": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e"
                      },
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Follow-up from external system",
                        "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "last_author_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "last_message_created_at": "2026-02-18T10:04:15.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:05:10.277962Z"
                      }
                    }
                  },
                  "reply": {
                    "summary": "Threaded reply",
                    "value": {
                      "message": {
                        "id": "m_032Kw5BC3EWyjHk83UydbF",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_zLqW4mDNJBHc2",
                        "body": "Thanks Alice. Can you share the URL and a screenshot? I'll also check our auth logs on this end.",
                        "reply_to": "m_032Kw4XA2DVxiGj72TxcaE",
                        "reply_to_message_excerpt": "Hi — I can't log in after resetting my password. The reset link said success but I'm getting \"invalid credentials\" on every attempt.",
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:04:15.277962Z",
                        "idempotency_key": "9c1d2e7f-3b4a-4f6c-8a1e-5d8f3c7a9b1d"
                      },
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Thanks Alice. Can you share the URL and a screenshot? I'll also check our auth logs on this end.",
                        "last_message_id": "m_032Kw5BC3EWyjHk83UydbF",
                        "last_author_ids": [
                          "u_zLqW4mDNJBHc2"
                        ],
                        "last_message_created_at": "2026-02-18T10:04:15.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:05:10.277962Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/messages/{message_id}": {
      "get": {
        "tags": [
          "Messages"
        ],
        "operationId": "getThreadMessage",
        "summary": "Retrieve message in thread",
        "description": "Preferred endpoint for retrieving a single message scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed.\nReturns `404` when the message does not belong to the provided `thread_id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          }
        ],
        "responses": {
          "200": {
            "description": "Message object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Message"
                },
                "examples": {
                  "success": {
                    "value": {
                      "id": "m_032Kw4XA2DVxiGj72TxcaE",
                      "object": "message",
                      "thread_id": "th_fmn8SsKHoavown2s",
                      "user_id": "u_tgJfNUiC1nDV4",
                      "body": "Follow-up from external system",
                      "reply_to_message_excerpt": null,
                      "sub_thread_id": null,
                      "created_at": "2026-02-18T10:04:15.277962Z"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "Messages"
        ],
        "operationId": "updateThreadMessage",
        "summary": "Update message in thread",
        "description": "Preferred endpoint for full message update scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed.\nReturns `404` when the message does not belong to the provided `thread_id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageUpdateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "message": {
                      "body": "Updated follow-up text"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageUpdateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "body": "Updated follow-up text",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:04:15.277962Z",
                        "updated_at": "2026-02-18T10:08:24.277962Z",
                        "edited_at": "2026-02-18T10:08:24Z"
                      },
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Updated follow-up text",
                        "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "last_author_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "last_message_created_at": "2026-02-18T10:04:15.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:05:10.277962Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      },
      "patch": {
        "tags": [
          "Messages"
        ],
        "operationId": "patchThreadMessage",
        "summary": "Patch message in thread",
        "description": "Preferred endpoint for partial message update scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed or when the `message` body is missing.\nReturns `404` when the message does not belong to the provided `thread_id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MessageUpdateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "message": {
                      "body": "Patched follow-up text"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Message was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageUpdateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "body": "Patched follow-up text",
                        "reply_to_message_excerpt": null,
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:04:15.277962Z",
                        "updated_at": "2026-02-18T10:08:24.277962Z",
                        "edited_at": "2026-02-18T10:08:24Z"
                      },
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Patched follow-up text",
                        "last_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "last_author_ids": [
                          "u_tgJfNUiC1nDV4"
                        ],
                        "last_message_created_at": "2026-02-18T10:04:15.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:05:10.277962Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      },
      "delete": {
        "tags": [
          "Messages"
        ],
        "operationId": "deleteThreadMessage",
        "summary": "Delete message in thread",
        "description": "Preferred endpoint for deleting a message scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed.\nReturns `404` when the message does not belong to the provided `thread_id`.\nThread owners can delete any message in the thread.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          }
        ],
        "responses": {
          "200": {
            "description": "Message was deleted.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageDeleteResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "sub_thread_id": null,
                        "created_at": "2026-02-18T10:04:15.277962Z",
                        "updated_at": "2026-02-18T11:14:33.277962Z",
                        "deleted_at": "2026-02-18T11:14:33.277962Z"
                      },
                      "message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                      "deleted_at": "2026-02-18T11:14:33.277962Z",
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "description": null,
                        "last_message_excerpt": "Initial import message",
                        "last_message_id": "m_032Kw5BC3EWyjHk83UydbF",
                        "last_author_ids": [
                          "u_zLqW4mDNJBHc2"
                        ],
                        "last_message_created_at": "2026-02-18T10:03:58.277962Z",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:03:58.277962Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/threads/{thread_id}/messages/{message_id}/reactions": {
      "post": {
        "tags": [
          "Messages"
        ],
        "operationId": "addThreadMessageReaction",
        "summary": "Add reaction to message in thread",
        "description": "Preferred endpoint for adding a reaction to a message scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed.\nReturns `404` when the message does not belong to the provided `thread_id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReactionCreateRequest"
              },
              "examples": {
                "thumbsUp": {
                  "value": {
                    "name": "thumbs_up"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reaction was added.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionAddResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/threads/{thread_id}/messages/{message_id}/reactions/{name}": {
      "delete": {
        "tags": [
          "Messages"
        ],
        "operationId": "removeThreadMessageReaction",
        "summary": "Remove reaction from message in thread",
        "description": "Preferred endpoint for removing a reaction from a message scoped to a thread.\nReturns `400` when the `thread_id` or `message_id` is malformed.\nReturns `404` when the message does not belong to the provided `thread_id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "$ref": "#/components/parameters/MessageId"
          },
          {
            "$ref": "#/components/parameters/ReactionName"
          }
        ],
        "responses": {
          "200": {
            "description": "Reaction was removed.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionRemoveResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                      "thread_id": "th_fmn8SsKHoavown2s",
                      "user_id": "u_tgJfNUiC1nDV4",
                      "name": "thumbs_up"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/integrations": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "operationId": "listIntegrations",
        "summary": "List integrations",
        "description": "Lists integrations visible to the caller. A personal access token sees all integrations\nthe user has created; a bot sees only the integrations it directly created.\n",
        "responses": {
          "200": {
            "description": "Integration list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationListResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "data": [
                        {
                          "id": "int_Hs4kPq9Lm2Vx7Cd",
                          "object": "integration",
                          "name": "Acme Support Sync",
                          "status": "active",
                          "type": "personal_token",
                          "token_last_four": "f3A9",
                          "webhook_url": "https://example.com/webhooks/birdychat",
                          "last_ip": "203.0.113.42",
                          "email": "alice.finch@example.com",
                          "last_used_at": "2026-02-18T10:03:57Z",
                          "created_at": "2026-02-18T10:03:57Z",
                          "updated_at": "2026-02-18T10:03:57Z"
                        }
                      ],
                      "object": "list",
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Integrations"
        ],
        "operationId": "createIntegration",
        "summary": "Create integration",
        "description": "Creates an integration. A `personal_token` acts as the creator; a `bot` gets its own user.\nThe `token` (and, when a `webhook_url` is set, the `webhook_signing_secret`) are returned\nonly once in this response and cannot be retrieved later.\n\nReturns `403` when the account's active integration limit is reached or when a bot attempts\nto create a `personal_token`, and `429` when too many are created in a short period.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationCreateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "integration": {
                      "name": "Acme Support Sync",
                      "type": "personal_token",
                      "webhook_url": "https://example.com/webhooks/birdychat"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Integration was created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationCreateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "integration": {
                        "id": "int_Hs4kPq9Lm2Vx7Cd",
                        "object": "integration",
                        "name": "Acme Support Sync",
                        "status": "active",
                        "type": "personal_token",
                        "token_last_four": "f3A9",
                        "webhook_url": "https://example.com/webhooks/birdychat",
                        "last_ip": null,
                        "email": "alice.finch@example.com",
                        "last_used_at": null,
                        "created_at": "2026-02-18T10:03:57Z",
                        "updated_at": "2026-02-18T10:03:57Z"
                      },
                      "token": "sk_...",
                      "webhook_signing_secret": "whsec_..."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/integrations/{integration_id}": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "operationId": "getIntegration",
        "summary": "Retrieve integration",
        "description": "Retrieves a single visible integration. A personal access token sees any of the user's\nintegrations; a bot sees only the integrations it directly created.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IntegrationIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Integration object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "integration": {
                        "id": "int_Hs4kPq9Lm2Vx7Cd",
                        "object": "integration",
                        "name": "Acme Support Sync",
                        "status": "active",
                        "type": "personal_token",
                        "token_last_four": "f3A9",
                        "webhook_url": "https://example.com/webhooks/birdychat",
                        "last_ip": "203.0.113.42",
                        "email": "alice.finch@example.com",
                        "last_used_at": "2026-02-18T10:03:57Z",
                        "created_at": "2026-02-18T10:03:57Z",
                        "updated_at": "2026-02-18T10:03:57Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Integrations"
        ],
        "operationId": "updateIntegration",
        "summary": "Update integration",
        "description": "Updates an integration. Omitted fields are left unchanged; an empty `webhook_url` clears it.\nA `webhook_signing_secret` is returned only when setting a `webhook_url` on an integration\nthat has no signing secret yet.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IntegrationIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationUpdateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "integration": {
                      "name": "Acme Support Sync",
                      "webhook_url": "https://example.com/webhooks/birdychat"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Integration was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationUpdateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "integration": {
                        "id": "int_Hs4kPq9Lm2Vx7Cd",
                        "object": "integration",
                        "name": "Acme Support Sync",
                        "status": "active",
                        "type": "personal_token",
                        "token_last_four": "f3A9",
                        "webhook_url": "https://example.com/webhooks/birdychat",
                        "last_ip": "203.0.113.42",
                        "email": "alice.finch@example.com",
                        "last_used_at": "2026-02-18T10:03:57Z",
                        "created_at": "2026-02-18T10:03:57Z",
                        "updated_at": "2026-02-18T10:03:57Z"
                      },
                      "webhook_signing_secret": "whsec_..."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The integration is revoked and can't be updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Integrations"
        ],
        "operationId": "revokeIntegration",
        "summary": "Revoke integration",
        "description": "Revokes the integration's token.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IntegrationIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Integration was revoked.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "integration": {
                        "id": "int_Hs4kPq9Lm2Vx7Cd",
                        "object": "integration",
                        "name": "Acme Support Sync",
                        "status": "revoked",
                        "type": "personal_token",
                        "token_last_four": "f3A9",
                        "webhook_url": "https://example.com/webhooks/birdychat",
                        "last_ip": "203.0.113.42",
                        "email": "alice.finch@example.com",
                        "last_used_at": "2026-02-18T10:03:57Z",
                        "created_at": "2026-02-18T10:03:57Z",
                        "updated_at": "2026-02-18T10:03:57Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/integrations/{integration_id}/avatar": {
      "put": {
        "tags": [
          "Integrations"
        ],
        "operationId": "updateIntegrationAvatar",
        "summary": "Set integration avatar",
        "description": "Sets the avatar for a bot integration. Only bot integrations have an avatar.\nUpload the image as multipart/form-data with an `avatar_file` field.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IntegrationIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationAvatarUpload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Avatar was set.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The integration is revoked and can't be updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "503": {
            "description": "Avatar storage is temporarily unavailable. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Integrations"
        ],
        "operationId": "deleteIntegrationAvatar",
        "summary": "Remove integration avatar",
        "description": "Removes the avatar from a bot integration. Only bot integrations have an avatar.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IntegrationIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Avatar was removed.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "description": "The integration is revoked and can't be updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "503": {
            "description": "Avatar storage is temporarily unavailable. Retry later.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/channels": {
      "get": {
        "tags": [
          "Channels"
        ],
        "operationId": "listChannels",
        "summary": "List channels",
        "description": "Lists channels visible to the authenticated integration user.\nIncludes system channels (`inbox`, `snoozed`, `archive`) and personal channels.\n",
        "responses": {
          "200": {
            "description": "Channel list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelListResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "data": [
                        {
                          "id": "ch_DNb4kFmRhJp9wT",
                          "object": "channel",
                          "name": "Inbox",
                          "role": "inbox",
                          "order": 0,
                          "deleted_at": null,
                          "created_at": "2026-02-18T10:03:57.277962Z",
                          "updated_at": "2026-02-18T10:03:57.277962Z"
                        },
                        {
                          "id": "ch_7sUNVzywAU8CGi",
                          "object": "channel",
                          "name": "Customer followups",
                          "role": "personal",
                          "order": 1771409037.277962,
                          "deleted_at": null,
                          "created_at": "2026-02-18T10:03:57.277962Z",
                          "updated_at": "2026-02-18T10:03:57.277962Z",
                          "icon": {
                            "color": "blue",
                            "emoji": ":pushpin:"
                          }
                        }
                      ],
                      "object": "list",
                      "has_more": false
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Channels"
        ],
        "operationId": "createChannel",
        "summary": "Create channel",
        "description": "Creates a personal channel for the authenticated integration user.\n\nUse the `Idempotency-Key` request header to deduplicate requests.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelCreateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "channel": {
                      "name": "Customer followups",
                      "icon": {
                        "color": "blue",
                        "emoji": ":pushpin:"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Channel was created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelCreateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "channel": {
                        "id": "ch_7sUNVzywAU8CGi",
                        "object": "channel",
                        "name": "Customer followups",
                        "role": "personal",
                        "order": 1771409037.277962,
                        "deleted_at": null,
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:03:57.277962Z",
                        "icon": {
                          "color": "blue",
                          "emoji": ":pushpin:"
                        },
                        "idempotency_key": "c3d4e5f6-a7b8-4c9d-0e1f-2a3b4c5d6e7f"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          }
        }
      }
    },
    "/channels/{channel_id}": {
      "get": {
        "tags": [
          "Channels"
        ],
        "operationId": "getChannel",
        "summary": "Retrieve channel",
        "description": "Retrieves a single visible channel by id.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Channel object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Channel"
                },
                "examples": {
                  "success": {
                    "value": {
                      "id": "ch_7sUNVzywAU8CGi",
                      "object": "channel",
                      "name": "Customer followups",
                      "role": "personal",
                      "order": 1771409037.277962,
                      "deleted_at": null,
                      "created_at": "2026-02-18T10:03:57.277962Z",
                      "updated_at": "2026-02-18T10:03:57.277962Z",
                      "icon": {
                        "color": "blue",
                        "emoji": ":pushpin:"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "tags": [
          "Channels"
        ],
        "operationId": "updateChannel",
        "summary": "Update channel",
        "description": "Fully updates a mutable channel.\nSystem channels are immutable and return `403`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelUpdateRequest"
              },
              "examples": {
                "rename": {
                  "value": {
                    "channel": {
                      "name": "Customer followups urgent"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Channel was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelUpdateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "channel": {
                        "id": "ch_7sUNVzywAU8CGi",
                        "object": "channel",
                        "name": "Customer followups urgent",
                        "role": "personal",
                        "order": 1771409037.277962,
                        "deleted_at": null,
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:03:57.277962Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Channel cannot be updated because it is not mutable.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "systemChannel": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "permission_denied",
                        "message": "Can't update channel",
                        "description": "System channels cannot be updated"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found or not visible to the integration user.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "notFound": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "not_found",
                        "message": "Can't update channel",
                        "description": "Channel not found"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation failed for the channel payload.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidOrder": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "invalid_params",
                        "message": "Can't update channel",
                        "description": "Order must be greater than or equal to 0"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Channels"
        ],
        "operationId": "patchChannel",
        "summary": "Patch channel",
        "description": "Partially updates a mutable channel.\nSystem channels are immutable and return `403`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChannelUpdateRequest"
              },
              "examples": {
                "iconUpdate": {
                  "value": {
                    "channel": {
                      "icon": {
                        "color": "green",
                        "emoji": ":white_check_mark:"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Channel was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelUpdateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "channel": {
                        "id": "ch_7sUNVzywAU8CGi",
                        "object": "channel",
                        "name": "Customer followups",
                        "role": "personal",
                        "order": 1771409037.277962,
                        "deleted_at": null,
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:03:57.277962Z",
                        "icon": {
                          "color": "green",
                          "emoji": ":white_check_mark:"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Channel cannot be updated because it is not mutable.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "systemChannel": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "permission_denied",
                        "message": "Can't update channel",
                        "description": "System channels cannot be updated"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found or not visible to the integration user.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "notFound": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "not_found",
                        "message": "Can't update channel",
                        "description": "Channel not found"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation failed for the channel payload.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidOrder": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "invalid_params",
                        "message": "Can't update channel",
                        "description": "Order must be greater than or equal to 0"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Channels"
        ],
        "operationId": "deleteChannel",
        "summary": "Delete channel",
        "description": "Soft-deletes a personal channel.\nSystem channels cannot be deleted and return `403`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Channel was deleted.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelDeleteResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "channel_id": "ch_7sUNVzywAU8CGi",
                      "deleted_at": "2026-02-18T10:03:57.277962Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Delete is forbidden for system channels.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "systemChannelForbidden": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "forbidden",
                        "message": "Can't delete channel",
                        "description": "Cannot delete system channels"
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Channel not found or not visible to the integration user.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "notFound": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "not_found",
                        "message": "Can't delete channel",
                        "description": "Channel not found"
                      }
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Invalid channel id payload.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidChannelId": {
                    "value": {
                      "error": {
                        "type": "bad_request",
                        "code": "invalid_channel_id",
                        "message": "Can't delete channel",
                        "description": "Invalid channel ID format"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/attachments": {
      "post": {
        "tags": [
          "Attachments"
        ],
        "operationId": "createAttachment",
        "summary": "Create attachment metadata",
        "description": "Creates attachment metadata and returns a signed upload URL.\nThis endpoint does not upload file bytes.\nUpload the file (max 10 MB) by POSTing to the signed `attachment.upload_url`\nas multipart/form-data with a `file` field.\n\nAfter uploading, include the attachment ID in the `attachments` array when\ncreating a message.\n\nUse the `Idempotency-Key` request header to deduplicate requests.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/attachments\" \\\n  -H \"Authorization: Bearer sk_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"filename\": \"screenshot-login-error.png\",\n    \"content_type\": \"image/png\",\n    \"size\": 204800\n  }'\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\npayload = {\n    \"filename\": \"screenshot-login-error.png\",\n    \"content_type\": \"image/png\",\n    \"size\": 204800,\n}\n\nresponse = requests.post(\n    \"https://birdy.chat/api/v1/attachments\",\n    headers={\n        \"Authorization\": \"Bearer sk_...\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=payload,\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/attachments\", {\n  method: \"POST\",\n  headers: {\n    Authorization: \"Bearer sk_...\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    filename: \"screenshot-login-error.png\",\n    content_type: \"application/pdf\",\n    size: 204800,\n  }),\n});\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AttachmentCreateRequest"
              },
              "examples": {
                "default": {
                  "value": {
                    "filename": "screenshot-login-error.png",
                    "content_type": "image/png",
                    "size": 204800
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Attachment metadata created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentCreateResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "attachment": {
                        "id": "att_DT7QcSFMRe5mlz",
                        "upload_url": "https://media.birdy.chat/attachments/att_DT7QcSFMRe5mlz/upload?expires=1749638400&op=upload&sig=ab12cd34...",
                        "idempotency_key": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8a"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "422": {
            "description": "Attachment metadata validation failed (for example missing filename or invalid size).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidPayload": {
                    "value": {
                      "error": {
                        "message": "Can't create attachment",
                        "description": "Expected attachment metadata fields"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/attachments/{attachment_id}": {
      "get": {
        "tags": [
          "Attachments"
        ],
        "operationId": "getAttachment",
        "summary": "Retrieve attachment metadata",
        "parameters": [
          {
            "$ref": "#/components/parameters/AttachmentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Attachment"
                },
                "examples": {
                  "success": {
                    "value": {
                      "id": "att_DT7QcSFMRe5mlz",
                      "object": "attachment",
                      "type": "file",
                      "filename": "screenshot-login-error.png",
                      "content_type": "image/png",
                      "key": "att_DT7QcSFMRe5mlz.enc",
                      "size": 204800,
                      "status": "pending",
                      "user_id": "u_tgJfNUiC1nDV4",
                      "thread_id": null,
                      "message_id": null,
                      "width": null,
                      "height": null,
                      "preview_size": null,
                      "preview_width": null,
                      "preview_height": null,
                      "preview_status": null,
                      "created_at": "2026-02-18T10:03:57.277962Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundMessageOnly"
          }
        }
      },
      "delete": {
        "tags": [
          "Attachments"
        ],
        "operationId": "deleteAttachment",
        "summary": "Delete attachment",
        "description": "Soft-deletes an attachment visible to the integration user.",
        "parameters": [
          {
            "$ref": "#/components/parameters/AttachmentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment deleted.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttachmentDeleteResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "attachment_id": "att_DT7QcSFMRe5mlz"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundMessageOnly"
          },
          "422": {
            "description": "Attachment delete failed (for example attachment does not belong to current scope).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "notAllowed": {
                    "value": {
                      "error": {
                        "message": "Can't delete attachment",
                        "description": "User not in thread"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/attachments/{attachment_id}/download": {
      "get": {
        "tags": [
          "Attachments"
        ],
        "operationId": "downloadAttachment",
        "summary": "Download attachment",
        "description": "Redirects to a signed media service URL where the attachment can be downloaded.\nThe redirect URL includes a time-limited signature for authentication.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/AttachmentId"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to signed media service download URL.",
            "headers": {
              "location": {
                "description": "Signed media service URL for downloading the attachment.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundMessageOnly"
          }
        }
      }
    },
    "/attachments/{attachment_id}/download/preview": {
      "get": {
        "tags": [
          "Attachments"
        ],
        "operationId": "downloadAttachmentPreview",
        "summary": "Download attachment preview",
        "description": "Redirects to a signed media service URL where the attachment preview can be downloaded.\nThe redirect URL includes a time-limited signature for authentication.\nIf the preview is still being processed, the media service responds with 202 Accepted.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/AttachmentId"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to signed media service preview download URL.",
            "headers": {
              "location": {
                "description": "Signed media service URL for downloading the attachment preview.",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              },
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundMessageOnly"
          }
        }
      }
    },
    "/users": {
      "get": {
        "tags": [
          "Users"
        ],
        "operationId": "listUsers",
        "summary": "List related users",
        "description": "Returns users visible to the current integration when filtering by `user_ids`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/UserIds"
          }
        ],
        "responses": {
          "200": {
            "description": "User list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "data": [
                        {
                          "id": "u_tgJfNUiC1nDV4",
                          "object": "user",
                          "name": "Alice Finch",
                          "display_name": "Alice Finch",
                          "email": "alice.finch@example.com",
                          "avatar_small_path": "/uploads/alice-finch-avatar.png",
                          "avatar_small_url": "https://birdy.chat/uploads/alice-finch-avatar.png",
                          "avatar_large_path": "/uploads/alice-finch-avatar-large.png"
                        }
                      ],
                      "object": "list",
                      "has_more": false,
                      "next_cursor": null,
                      "prev_cursor": null
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/users/{user_id}": {
      "get": {
        "tags": [
          "Users"
        ],
        "operationId": "getUser",
        "summary": "Retrieve user",
        "parameters": [
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "User object.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                },
                "examples": {
                  "success": {
                    "value": {
                      "id": "u_tgJfNUiC1nDV4",
                      "object": "user",
                      "name": "Alice Finch",
                      "display_name": "Alice Finch",
                      "email": "alice.finch@example.com",
                      "avatar_small_path": "/uploads/alice-finch-avatar.png",
                      "avatar_small_url": "https://birdy.chat/uploads/alice-finch-avatar.png",
                      "avatar_large_path": "/uploads/alice-finch-avatar-large.png",
                      "profile": {
                        "title": "Customer Success Lead",
                        "company": "Acme Inc.",
                        "website": "https://example.com",
                        "about_me": "Helping customers ship faster."
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/scheduled_messages": {
      "get": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "listScheduledMessages",
        "summary": "List scheduled messages",
        "description": "Returns the authenticated user's pending scheduled messages.\nOptionally filter by thread.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/scheduled_messages\" \\\n  -H \"Authorization: Bearer sk_...\"\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://birdy.chat/api/v1/scheduled_messages\",\n    headers={\"Authorization\": \"Bearer sk_...\"},\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/scheduled_messages\", {\n  headers: { Authorization: \"Bearer sk_...\" }\n});\nconst data = await response.json();\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Scheduled message list.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "createScheduledMessage",
        "summary": "Create scheduled message",
        "description": "Creates a scheduled message in the specified thread.\nThe message will be sent automatically at the specified `scheduled_at` time.\n\nSupports `Idempotency-Key` header for safe retries.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/scheduled_messages\" \\\n  -H \"Authorization: Bearer sk_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"thread_id\":\"th_fmn8SsKHoavown2s\",\"scheduled_at\":\"2026-03-01T10:00:00Z\",\"message\":{\"body\":\"Scheduled follow-up message\"}}'\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\npayload = {\n    \"thread_id\": \"th_fmn8SsKHoavown2s\",\n    \"scheduled_at\": \"2026-03-01T10:00:00Z\",\n    \"message\": {\"body\": \"Scheduled follow-up message\"},\n}\n\nresponse = requests.post(\n    \"https://birdy.chat/api/v1/scheduled_messages\",\n    headers={\n        \"Authorization\": \"Bearer sk_...\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=payload,\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/scheduled_messages\", {\n  method: \"POST\",\n  headers: {\n    Authorization: \"Bearer sk_...\",\n    \"Content-Type\": \"application/json\"\n  },\n  body: JSON.stringify({\n    thread_id: \"th_fmn8SsKHoavown2s\",\n    scheduled_at: \"2026-03-01T10:00:00Z\",\n    message: { body: \"Scheduled follow-up message\" }\n  })\n});\nconst data = await response.json();\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduledMessageCreateRequest"
              },
              "examples": {
                "default": {
                  "summary": "Text message",
                  "value": {
                    "thread_id": "th_fmn8SsKHoavown2s",
                    "scheduled_at": "2026-03-01T10:00:00Z",
                    "message": {
                      "body": "Scheduled follow-up message"
                    }
                  }
                },
                "withAttachments": {
                  "summary": "Message with attachments",
                  "value": {
                    "thread_id": "th_fmn8SsKHoavown2s",
                    "scheduled_at": "2026-03-01T10:00:00Z",
                    "message": {
                      "body": "See attached report",
                      "attachments": [
                        {
                          "id": "att_DT7QcSFMRe5mlz"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Scheduled message was created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimit"
          }
        }
      }
    },
    "/scheduled_messages/{scheduled_message_id}": {
      "get": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "getScheduledMessage",
        "summary": "Retrieve scheduled message",
        "description": "Returns a single pending scheduled message by ID.\nOnly the user who created the scheduled message can retrieve it.\nProcessed scheduled messages are not returned.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ScheduledMessageId"
          }
        ],
        "responses": {
          "200": {
            "description": "Scheduled message details.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "updateScheduledMessage",
        "summary": "Update scheduled message",
        "description": "Updates the `scheduled_at` time and/or the `message` content of a\npending scheduled message. At least one field must be provided.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ScheduledMessageId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduledMessageUpdateRequest"
              },
              "examples": {
                "updateTime": {
                  "summary": "Reschedule",
                  "value": {
                    "scheduled_at": "2026-03-02T14:00:00Z"
                  }
                },
                "updateBody": {
                  "summary": "Change message body",
                  "value": {
                    "message": {
                      "body": "Updated content"
                    }
                  }
                },
                "updateAttachments": {
                  "summary": "Update attachments",
                  "value": {
                    "message": {
                      "attachments": [
                        {
                          "id": "att_DT7QcSFMRe5mlz"
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scheduled message was updated.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "deleteScheduledMessage",
        "summary": "Delete scheduled message",
        "description": "Deletes a pending scheduled message. The message will not be sent.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ScheduledMessageId"
          }
        ],
        "responses": {
          "200": {
            "description": "Scheduled message was deleted.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageDeleteResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/scheduled_messages/{scheduled_message_id}/send": {
      "post": {
        "tags": [
          "Scheduled Messages"
        ],
        "operationId": "sendScheduledMessage",
        "summary": "Send scheduled message immediately",
        "description": "Sends a pending scheduled message immediately, bypassing the\nscheduled time. The scheduled message is marked as processed\nand a regular message is created in the thread.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ScheduledMessageId"
          }
        ],
        "responses": {
          "200": {
            "description": "Scheduled message was sent.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduledMessageSendResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/events": {
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "listEvents",
        "summary": "List canonical events",
        "description": "Returns canonical events visible to the authenticated integration.\nResults are sorted newest-first (descending by event id) and can be filtered by type and thread.\n",
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl -sS \"https://birdy.chat/api/v1/events?limit=10\" \\\n  -H \"Authorization: Bearer sk_...\"\n"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://birdy.chat/api/v1/events\",\n    headers={\"Authorization\": \"Bearer sk_...\"},\n    params={\"limit\": 10, \"type\": \"message.created\"},\n    timeout=30,\n)\nprint(response.json())\n"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "const response = await fetch(\"https://birdy.chat/api/v1/events?limit=10\", {\n  headers: { Authorization: \"Bearer sk_...\" }\n});\nconst data = await response.json();\nconsole.log(data);\n"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/EventStartingAfter"
          },
          {
            "$ref": "#/components/parameters/EventEndingBefore"
          },
          {
            "$ref": "#/components/parameters/EventType"
          },
          {
            "$ref": "#/components/parameters/ThreadIdQuery"
          },
          {
            "$ref": "#/components/parameters/EventLimit"
          },
          {
            "$ref": "#/components/parameters/EventTimeout"
          }
        ],
        "responses": {
          "200": {
            "description": "Event list response.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventListResponse"
                },
                "examples": {
                  "success": {
                    "value": {
                      "object": "list",
                      "data": [
                        {
                          "id": "e_032Kw4XA2DVxiGj72TxcaE",
                          "object": "event",
                          "type": "message.created",
                          "created_at": "2026-02-18T10:03:58.277962Z",
                          "data": {
                            "message": {
                              "id": "m_032Kw4XA2DVxiGj72TxcaE"
                            }
                          }
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null,
                      "previous_cursor": "e_032Kw4XA2DVxiGj72TxcaE"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/events/socket": {
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "openEventsSocket",
        "summary": "Open integration events WebSocket",
        "description": "Upgrades the HTTP connection to a read-only WebSocket that streams\ncanonical events for the authenticated integration. Each frame is a\nJSON-encoded `Event` — the same shape returned by `GET /events`.\n\nOpenAPI only describes the upgrade handshake. Message payloads,\nframe direction, and close codes are documented in the companion\nAsyncAPI specification linked via `x-async-api`.\n\nBehavior summary:\n- Auth: `Authorization: Bearer sk_...` (same as the REST API).\n- Resume: pass `?cursor=e_...` to start after a specific event id.\n  Omit to start from the newest event at connection time.\n- Read-only: any inbound client frame closes the connection with\n  WebSocket code 1008.\n",
        "x-async-api": "./events-socket.asyncapi.yaml",
        "parameters": [
          {
            "name": "Connection",
            "in": "header",
            "required": true,
            "description": "Must include the `Upgrade` token (case-insensitive). May be a\ncomma-separated list, e.g. `keep-alive, Upgrade`.\n",
            "schema": {
              "type": "string"
            },
            "example": "keep-alive, Upgrade"
          },
          {
            "name": "Upgrade",
            "in": "header",
            "required": true,
            "description": "Must be `websocket`.",
            "schema": {
              "type": "string",
              "enum": [
                "websocket"
              ]
            }
          },
          {
            "name": "Sec-WebSocket-Version",
            "in": "header",
            "required": true,
            "description": "RFC 6455 version; must be `13`.",
            "schema": {
              "type": "string",
              "enum": [
                "13"
              ]
            }
          },
          {
            "name": "Sec-WebSocket-Key",
            "in": "header",
            "required": true,
            "description": "Base64-encoded 16-byte client nonce (RFC 6455).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Resume after this event id. Omit to start from the newest event\nat connection time. Sending an empty string or a value without\nthe `e_` prefix rejects the upgrade with HTTP 400\n`invalid_cursor`.\n",
            "schema": {
              "type": "string",
              "pattern": "^e_.+"
            }
          }
        ],
        "responses": {
          "101": {
            "description": "Switching Protocols — WebSocket established. The server pushes\n`Event` JSON text frames. See the AsyncAPI document referenced\nby `x-async-api` for the message schema and close codes.\n"
          },
          "400": {
            "description": "Invalid cursor.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "invalidCursor": {
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "invalid_cursor",
                        "message": "Can't connect events stream",
                        "description": "Invalid cursor"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or invalid integration token.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "missingToken": {
                    "value": {
                      "error": {
                        "type": "invalid_request_error",
                        "code": "missing_token",
                        "message": "Can't connect events stream",
                        "description": "Missing or invalid token"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "integrationEvent": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "receiveIntegrationEvent",
        "summary": "Outbound integration webhook delivery",
        "description": "BirdyChat sends this webhook to integration-configured webhook URLs.\nEvents are delivered asynchronously and may be retried.\nDelivery scope by event type:\n- integration-auth create events:\n  - `channel.created`\n  - `attachment.created`\n  These are integration-scoped events (not participant fanout).\n- participant fanout events:\n  - `thread.left`\n  - `message.updated`\n  - `message.deleted`\n  - `message.reaction.created`\n  - `message.reaction.deleted`\n- request-scoped personal lifecycle events:\n  - `thread.archived`\n  - `thread.snoozed`\n  - `thread.moved`\n  - `thread.mark_read`\n  These do not fan out to participant integrations.\n- hybrid:\n  - `thread.created` can be sent for integration-auth create and also participant fanout.\n  - `message.created` can be sent for integration-auth create and also participant fanout.\nFor integration-auth fanout paths, the origin integration is excluded from participant fanout.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/XBirdyTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/XBirdySignatureHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              },
              "examples": {
                "subThreadCreated": {
                  "summary": "Sub-thread created",
                  "value": {
                    "id": "evt_032Kw4XA2DVxiGj72TxcaE",
                    "object": "event",
                    "type": "thread.created",
                    "created_at": "2026-02-18T10:05:00.000000Z",
                    "data": {
                      "thread": {
                        "id": "th_9xKpQ3mRvNwT2hYs",
                        "object": "thread",
                        "name": "Check out https://example.com/page",
                        "user_ids": [],
                        "users": [],
                        "users_count": 0,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "parent_thread_id": "th_fmn8SsKHoavown2s",
                        "parent_message_id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "joined": true,
                        "created_at": "2026-02-18T10:05:00.000000Z",
                        "updated_at": "2026-02-18T10:05:00.000000Z"
                      }
                    }
                  }
                },
                "threadArchived": {
                  "value": {
                    "id": "evt_032Kw4XA2DVxiGj72TxcaE",
                    "object": "event",
                    "type": "thread.archived",
                    "created_at": "2026-02-18T10:03:57.277962Z",
                    "data": {
                      "thread_id": "th_fmn8SsKHoavown2s",
                      "archived_at": "2026-02-18T10:03:57.277962Z"
                    }
                  }
                },
                "messageUpdated": {
                  "value": {
                    "id": "evt_032Kw5BC3EWyjHk83UydbF",
                    "object": "event",
                    "type": "message.updated",
                    "created_at": "2026-02-18T10:05:10.277962Z",
                    "data": {
                      "message": {
                        "id": "m_032Kw4XA2DVxiGj72TxcaE",
                        "object": "message",
                        "thread_id": "th_fmn8SsKHoavown2s",
                        "body": "Updated body",
                        "user_id": "u_tgJfNUiC1nDV4",
                        "created_at": "2026-02-18T10:03:57.277962Z"
                      },
                      "thread": {
                        "id": "th_fmn8SsKHoavown2s",
                        "object": "thread",
                        "name": "Customer onboarding",
                        "user_ids": [
                          "u_tgJfNUiC1nDV4",
                          "u_zLqW4mDNJBHc2"
                        ],
                        "users": [
                          {
                            "user_id": "u_tgJfNUiC1nDV4",
                            "roles": [
                              "creator",
                              "owner"
                            ]
                          },
                          {
                            "user_id": "u_zLqW4mDNJBHc2",
                            "roles": []
                          }
                        ],
                        "users_count": 2,
                        "settings": {
                          "is_sharing_enabled": false
                        },
                        "created_at": "2026-02-18T10:03:57.277962Z",
                        "updated_at": "2026-02-18T10:05:10.277962Z"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Receiver accepted the event."
          },
          "204": {
            "description": "Receiver accepted with no content."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_token"
      }
    },
    "parameters": {
      "ThreadId": {
        "name": "thread_id",
        "in": "path",
        "required": true,
        "description": "Prefixed thread id (`th_...`).",
        "schema": {
          "type": "string",
          "pattern": "^th_.+"
        }
      },
      "ThreadIdQueryRequired": {
        "name": "thread_id",
        "in": "query",
        "required": true,
        "description": "Prefixed thread id (`th_...`).",
        "schema": {
          "type": "string",
          "pattern": "^th_.+"
        }
      },
      "ThreadIdQuery": {
        "name": "thread_id",
        "in": "query",
        "required": false,
        "description": "Optional prefixed thread id (`th_...`).",
        "schema": {
          "type": "string",
          "pattern": "^th_.+"
        }
      },
      "MessageId": {
        "name": "message_id",
        "in": "path",
        "required": true,
        "description": "Prefixed message id (`m_...`).",
        "schema": {
          "type": "string",
          "pattern": "^m_.+"
        }
      },
      "ReactionName": {
        "name": "name",
        "in": "path",
        "required": true,
        "description": "Reaction name.",
        "schema": {
          "type": "string"
        }
      },
      "UserId": {
        "name": "user_id",
        "in": "path",
        "required": true,
        "description": "Prefixed user id (`u_...`).",
        "schema": {
          "type": "string",
          "pattern": "^u_.+"
        }
      },
      "ChannelId": {
        "name": "channel_id",
        "in": "query",
        "required": false,
        "description": "Optional prefixed channel id (`ch_...`).",
        "schema": {
          "type": "string",
          "pattern": "^ch_.+"
        }
      },
      "ParentThreadId": {
        "name": "parent_thread_id",
        "in": "query",
        "required": false,
        "description": "List sub-threads of a given parent thread (`th_...`). Mutually exclusive with `channel_id` — do not pass both.",
        "schema": {
          "type": "string",
          "pattern": "^th_.+"
        }
      },
      "ChannelIdPath": {
        "name": "channel_id",
        "in": "path",
        "required": true,
        "description": "Prefixed channel id (`ch_...`) for a visible channel.",
        "schema": {
          "type": "string",
          "pattern": "^ch_.+"
        }
      },
      "IntegrationIdPath": {
        "name": "integration_id",
        "in": "path",
        "required": true,
        "description": "Prefixed integration id (`int_...`) of an integration visible to the caller.",
        "schema": {
          "type": "string",
          "pattern": "^int_.+"
        }
      },
      "AttachmentId": {
        "name": "attachment_id",
        "in": "path",
        "required": true,
        "description": "Prefixed attachment id (`att_...`) visible to current integration scope.",
        "schema": {
          "type": "string",
          "pattern": "^att_.+"
        }
      },
      "ScheduledMessageId": {
        "name": "scheduled_message_id",
        "in": "path",
        "required": true,
        "description": "Prefixed scheduled message id (`sm_...`).",
        "schema": {
          "type": "string",
          "pattern": "^sm_.+"
        }
      },
      "Role": {
        "name": "role",
        "in": "path",
        "required": true,
        "description": "Thread membership role.\n- `owner`: can be granted/revoked with role endpoints.\n- `creator`: automatically set for the thread creator and cannot be granted/revoked.\n",
        "schema": {
          "type": "string",
          "enum": [
            "owner"
          ],
          "example": "owner"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of records to return.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "EventLimit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum number of events to return.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 10
        }
      },
      "EventTimeout": {
        "name": "timeout",
        "in": "query",
        "required": false,
        "description": "Long-poll timeout in seconds. When provided and no events are currently available,\nthe request waits until new events arrive or timeout is reached.\nSupported for baseline/`ending_before` polling. Invalid when combined with `starting_after`.\n",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 30,
          "default": 0
        }
      },
      "EventStartingAfter": {
        "name": "starting_after",
        "in": "query",
        "required": false,
        "description": "Cursor pointing to an event ID (`e_...`). Returns events that come after this one\nin the result list order. Because events are sorted newest-first, this gives you\n*older* events — use this to paginate backward into history.\nMutually exclusive with `ending_before`.\n",
        "schema": {
          "type": "string",
          "pattern": "^e_.+"
        }
      },
      "EventEndingBefore": {
        "name": "ending_before",
        "in": "query",
        "required": false,
        "description": "Cursor pointing to an event ID (`e_...`). Returns the page of events immediately\nnewer than this one (adjacent to the cursor), in newest-first order. Paginate forward\ncontiguously by passing each response's `previous_cursor` back as `ending_before`.\nMutually exclusive with `starting_after`.\n",
        "schema": {
          "type": "string",
          "pattern": "^e_.+"
        }
      },
      "EventType": {
        "name": "type",
        "in": "query",
        "required": false,
        "description": "Filter by canonical event type.",
        "schema": {
          "type": "string",
          "enum": [
            "thread.created",
            "thread.updated",
            "thread.moved",
            "thread.joined",
            "thread.left",
            "thread.read",
            "thread.preferences.updated",
            "thread.deleted",
            "message.created",
            "message.updated",
            "message.deleted",
            "message.reaction.created",
            "message.reaction.deleted",
            "user.updated",
            "channel.created",
            "channel.updated",
            "channel.deleted",
            "scheduled_message.created",
            "scheduled_message.updated",
            "scheduled_message.deleted"
          ]
        }
      },
      "BeforeId": {
        "name": "before_id",
        "in": "query",
        "required": false,
        "description": "Cursor-based pagination token for fetching older records.",
        "schema": {
          "type": "string"
        }
      },
      "UserIds": {
        "name": "user_ids",
        "in": "query",
        "required": true,
        "description": "Comma-separated prefixed user ids (for example `u_...`).",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Idempotency for safely deduplicating retried requests.\n",
        "schema": {
          "type": "string"
        }
      },
      "XBirdyTimestampHeader": {
        "name": "x-birdy-timestamp",
        "in": "header",
        "required": true,
        "description": "Webhook unix timestamp header.",
        "schema": {
          "type": "string",
          "example": "1771409037"
        }
      },
      "XBirdySignatureHeader": {
        "name": "x-birdy-signature",
        "in": "header",
        "required": true,
        "description": "Webhook signature header in format `t=<timestamp>,v1=<hex_digest>`.",
        "schema": {
          "type": "string",
          "example": "t=1771409037,v1=8543e8d69262e24b1a25eb4cab298a6e7b447312cbf6e639ca35d71028f241bb"
        }
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Request identifier for troubleshooting.",
        "schema": {
          "type": "string"
        }
      },
      "XBirdyTimestamp": {
        "description": "Webhook unix timestamp header.",
        "schema": {
          "type": "string",
          "example": "1771409037"
        }
      },
      "XBirdySignature": {
        "description": "Webhook signature header in format `t=<timestamp>,v1=<hex_digest>`.",
        "schema": {
          "type": "string",
          "example": "t=1771409037,v1=8543e8d69262e24b1a25eb4cab298a6e7b447312cbf6e639ca35d71028f241bb"
        }
      }
    },
    "schemas": {
      "Event": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^e_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "event"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "thread.created",
              "thread.updated",
              "thread.moved",
              "thread.joined",
              "thread.left",
              "thread.read",
              "thread.preferences.updated",
              "thread.deleted",
              "message.created",
              "message.updated",
              "message.deleted",
              "message.reaction.created",
              "message.reaction.deleted",
              "user.updated",
              "channel.created",
              "channel.updated",
              "channel.deleted",
              "scheduled_message.created",
              "scheduled_message.updated",
              "scheduled_message.deleted"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "EventListResponse": {
        "type": "object",
        "required": [
          "object",
          "data",
          "has_more",
          "next_cursor",
          "previous_cursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor for the next page of older events. Pass as `starting_after` to paginate backward.\nNull when there are no more older events.\n"
          },
          "previous_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Cursor pointing to the newest event on this page. Pass as `ending_before` to fetch\nthe next contiguous page of newer events. Null when the page is empty.\n"
          }
        }
      },
      "ThreadUser": {
        "type": "object",
        "required": [
          "user_id",
          "roles"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "creator",
                "owner"
              ]
            }
          }
        }
      },
      "ThreadReadReceipt": {
        "type": "object",
        "required": [
          "message_id",
          "read_at"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "read_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ThreadSettings": {
        "type": "object",
        "properties": {
          "is_sharing_enabled": {
            "type": "boolean"
          },
          "is_email_digests_disabled": {
            "type": "boolean"
          },
          "is_participant_notifications_disabled": {
            "type": "boolean"
          },
          "participants_can_add_users": {
            "type": "boolean"
          }
        }
      },
      "Thread": {
        "type": "object",
        "required": [
          "id",
          "object",
          "name",
          "user_ids",
          "users",
          "users_count",
          "settings",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "thread"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "description": "Optional thread description text.",
            "type": [
              "string",
              "null"
            ]
          },
          "last_message_excerpt": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          },
          "last_author_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^u_.+"
            }
          },
          "last_message_created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^u_.+"
            }
          },
          "users": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadUser"
            }
          },
          "users_count": {
            "type": "integer"
          },
          "read_receipts": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/ThreadReadReceipt"
            }
          },
          "settings": {
            "$ref": "#/components/schemas/ThreadSettings"
          },
          "share_link": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "parent_thread_id": {
            "description": "ID of the parent thread. Present only for sub-threads.",
            "type": [
              "string",
              "null"
            ],
            "pattern": "^th_.+"
          },
          "parent_message_id": {
            "description": "ID of the parent message this sub-thread was created from. Present only for sub-threads.",
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          },
          "one_on_one_user_id_pair": {
            "description": "Sorted, comma-separated pair of user IDs (e.g. `u_abc,u_xyz`). Present only on one-on-one threads. Use this field to determine whether a thread is one-on-one.",
            "type": "string"
          },
          "joined": {
            "description": "Always present for sub-threads. Indicates whether the authenticated user follows this sub-thread. Since sub-thread `user_ids` is always empty, this is the only way to determine participation.",
            "type": "boolean"
          },
          "idempotency_key": {
            "type": "string"
          },
          "thread_user_preferences": {
            "description": "Per-user preferences for this thread. Only present when the authenticated user has preferences set (e.g. has snoozed or muted the thread).",
            "$ref": "#/components/schemas/ThreadUserPreferences"
          }
        }
      },
      "ThreadUserPreferences": {
        "type": "object",
        "required": [
          "thread_id"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "snoozed": {
            "description": "Present when the user has snoozed this thread at some point.",
            "type": "object",
            "properties": {
              "snoozed_until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "expired_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "muted": {
            "description": "Present when the user has muted this thread at some point.",
            "type": "object",
            "properties": {
              "muted_until": {
                "description": "Datetime until muted, or `\"forever\"` for permanent mute.",
                "type": [
                  "string",
                  "null"
                ]
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "sub_text": {
            "description": "Custom sub-text display for the thread.",
            "type": "object",
            "properties": {
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "surfaced": {
            "description": "Present when the thread has been surfaced to the user.",
            "type": "object",
            "properties": {
              "surfaced_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "ThreadListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Thread"
                }
              }
            }
          }
        ]
      },
      "MessageReaction": {
        "type": "object",
        "required": [
          "user_id",
          "created_at"
        ],
        "properties": {
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "variant": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "MessageAttachment": {
        "type": "object",
        "required": [
          "attachment_id",
          "type"
        ],
        "properties": {
          "attachment_id": {
            "type": "string",
            "pattern": "^att_.+"
          },
          "type": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          },
          "alt": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "width": {
            "type": "integer"
          },
          "height": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "preview_size": {
            "type": "integer"
          },
          "preview_width": {
            "type": "integer"
          },
          "preview_height": {
            "type": "integer"
          },
          "preview_status": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "path": {
            "type": "string",
            "description": "Relative path that redirects to the attachment download location."
          },
          "preview_path": {
            "type": "string",
            "description": "Relative path that redirects to the attachment preview download location."
          }
        }
      },
      "Message": {
        "type": "object",
        "required": [
          "id",
          "object",
          "thread_id",
          "user_id",
          "body",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "body": {
            "type": "string"
          },
          "reply_to_message_excerpt": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "edited_at": {
            "description": "Timestamp of when the message was last edited. Only present after a message has been updated.",
            "type": "string",
            "format": "date-time"
          },
          "reply_to": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          },
          "reactions": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "$ref": "#/components/schemas/MessageReaction"
              }
            }
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageAttachment"
            }
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true
          },
          "sub_thread_id": {
            "description": "ID of the sub-thread created from this message, if any.",
            "type": [
              "string",
              "null"
            ],
            "pattern": "^th_.+"
          },
          "idempotency_key": {
            "type": "string"
          }
        }
      },
      "MessageTombstone": {
        "description": "Minimal message object returned for deleted messages. Contains no body.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "object",
          "thread_id",
          "user_id",
          "created_at",
          "deleted_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "sub_thread_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^th_.+"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time"
          },
          "idempotency_key": {
            "type": "string"
          }
        }
      },
      "MessageListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Message"
                    },
                    {
                      "$ref": "#/components/schemas/MessageTombstone"
                    }
                  ]
                }
              }
            }
          }
        ]
      },
      "MessageCreatePayload": {
        "type": "object",
        "description": "At least one of `body` or `attachments` must be provided.\n",
        "anyOf": [
          {
            "required": [
              "body"
            ]
          },
          {
            "required": [
              "attachments"
            ]
          }
        ],
        "properties": {
          "body": {
            "type": "string"
          },
          "reply_to": {
            "type": "string",
            "pattern": "^m_.+",
            "description": "Prefixed message id to reply to."
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true
          },
          "attachments": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "pattern": "^att_.+"
                }
              }
            }
          }
        }
      },
      "MessageUpdatePayload": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "ThreadMessageCreateRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/MessageCreatePayload"
          }
        }
      },
      "MessageUpdateRequest": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/MessageUpdatePayload"
          }
        }
      },
      "MessageCreateResponse": {
        "type": "object",
        "required": [
          "message",
          "thread"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/Message"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          }
        }
      },
      "MessageUpdateResponse": {
        "type": "object",
        "required": [
          "message",
          "thread"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/Message"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          }
        }
      },
      "MessageDeleteResponse": {
        "type": "object",
        "required": [
          "message",
          "message_id",
          "thread",
          "deleted_at"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/MessageTombstone"
          },
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReactionCreateRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "variant": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ReactionAddResponse": {
        "type": "object",
        "required": [
          "message_id",
          "thread_id",
          "user_id",
          "name",
          "created_at"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "name": {
            "type": "string"
          },
          "variant": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ReactionRemoveResponse": {
        "type": "object",
        "required": [
          "message_id",
          "thread_id",
          "user_id",
          "name"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "MessageSummary": {
        "type": "object",
        "required": [
          "id",
          "thread_id",
          "body",
          "object"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "body": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "enum": [
              "message"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "reply_to_message_excerpt": {
            "type": [
              "string",
              "null"
            ]
          },
          "sub_thread_id": {
            "description": "ID of the sub-thread created from this message, if any.",
            "type": [
              "string",
              "null"
            ],
            "pattern": "^th_.+"
          }
        }
      },
      "ThreadCreateRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/RegularThreadCreateRequest"
          },
          {
            "$ref": "#/components/schemas/SubThreadCreateRequest"
          }
        ]
      },
      "RegularThreadCreateRequest": {
        "type": "object",
        "required": [
          "recipient_emails",
          "thread",
          "message"
        ],
        "properties": {
          "recipient_emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "channel_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ch_.+"
          },
          "thread": {
            "type": "object",
            "properties": {
              "name": {
                "description": "Thread name. Required for group threads. Omit for one-on-one threads (single recipient, no name).",
                "type": "string"
              }
            }
          },
          "message": {
            "type": "object",
            "description": "At least one of `body` or `attachments` must be provided.\n",
            "anyOf": [
              {
                "required": [
                  "body"
                ]
              },
              {
                "required": [
                  "attachments"
                ]
              }
            ],
            "properties": {
              "body": {
                "type": "string"
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "pattern": "^att_.+"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "SubThreadCreateRequest": {
        "type": "object",
        "required": [
          "parent_thread_id",
          "parent_message_id",
          "message"
        ],
        "properties": {
          "parent_thread_id": {
            "description": "ID of the parent thread. Must reference an existing non-sub-thread.",
            "type": "string",
            "pattern": "^th_.+"
          },
          "parent_message_id": {
            "description": "ID of the parent message. Must reference a message in the parent thread.",
            "type": "string",
            "pattern": "^m_.+"
          },
          "message": {
            "type": "object",
            "description": "At least one of `body` or `attachments` must be provided.\n",
            "anyOf": [
              {
                "required": [
                  "body"
                ]
              },
              {
                "required": [
                  "attachments"
                ]
              }
            ],
            "properties": {
              "body": {
                "type": "string"
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "pattern": "^att_.+"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ThreadCreateResponse": {
        "type": "object",
        "required": [
          "thread",
          "message"
        ],
        "properties": {
          "thread": {
            "$ref": "#/components/schemas/Thread"
          },
          "message": {
            "$ref": "#/components/schemas/MessageSummary"
          },
          "thread_in_channels": {
            "description": "Channel placements for the new thread. Present on regular thread creation.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          },
          "threads_in_channels": {
            "description": "Channel placements for the new sub-thread. Present on sub-thread creation.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          },
          "parent_message": {
            "description": "The updated parent message with `sub_thread_id` set. Present on sub-thread creation.",
            "$ref": "#/components/schemas/Message"
          }
        }
      },
      "ThreadAddUsersRequest": {
        "type": "object",
        "required": [
          "emails"
        ],
        "properties": {
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          }
        }
      },
      "ThreadRemoveUsersRequest": {
        "type": "object",
        "required": [
          "user_ids"
        ],
        "properties": {
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^u_.+"
            }
          }
        }
      },
      "ThreadRoleMutationRequest": {
        "type": "object",
        "required": [
          "user_ids"
        ],
        "properties": {
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^u_.+"
            }
          }
        }
      },
      "ThreadIdWithMessageId": {
        "type": "object",
        "required": [
          "thread_id",
          "message_id"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          }
        }
      },
      "ThreadArchiveRequest": {
        "type": "object",
        "required": [
          "thread_ids",
          "last_message_ids"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "last_message_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadIdWithMessageId"
            }
          },
          "archived_at": {
            "type": "string",
            "format": "date-time",
            "description": "Optional archive timestamp. Must include fractional seconds."
          }
        }
      },
      "ThreadSnoozeRequest": {
        "type": "object",
        "required": [
          "thread_ids",
          "snoozed_until",
          "last_message_ids"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "snoozed_until": {
            "type": "string",
            "format": "date-time",
            "description": "Must be at least 2 seconds in the future."
          },
          "last_message_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadIdWithMessageId"
            }
          },
          "snoozed_at": {
            "type": "string",
            "format": "date-time",
            "description": "Optional snooze timestamp. Must include fractional seconds."
          }
        }
      },
      "ThreadMoveRequest": {
        "type": "object",
        "required": [
          "thread_ids",
          "from_channel_id",
          "to_channel_id"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "from_channel_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ch_.+"
          },
          "to_channel_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ch_.+"
          },
          "moved_at": {
            "type": "string",
            "format": "date-time",
            "description": "Optional move timestamp. Must include fractional seconds."
          }
        }
      },
      "ThreadMuteRequest": {
        "type": "object",
        "required": [
          "thread_ids",
          "muted_until"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "muted_until": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO 8601 datetime (must be at least 2 seconds in the future), `\"forever\"`, or `null` to unmute."
          },
          "muted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Optional mute timestamp. Must include fractional seconds."
          }
        }
      },
      "ThreadReadRequest": {
        "type": "object",
        "required": [
          "thread_ids",
          "message_ids"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "message_ids": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadIdWithMessageId"
            }
          }
        }
      },
      "ThreadReadResponse": {
        "type": "object",
        "required": [
          "threads"
        ],
        "properties": {
          "threads": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "thread_id",
                "message_id"
              ],
              "properties": {
                "thread_id": {
                  "type": "string",
                  "pattern": "^th_.+"
                },
                "message_id": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "pattern": "^m_.+"
                }
              }
            }
          }
        }
      },
      "ThreadMarkReadRequest": {
        "type": "object",
        "required": [
          "message_id"
        ],
        "properties": {
          "message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+",
            "description": "Message id to mark as read, or `null` to mark as unread."
          }
        }
      },
      "ThreadInChannel": {
        "type": "object",
        "required": [
          "channel_id",
          "thread_id",
          "status",
          "updated_at"
        ],
        "properties": {
          "channel_id": {
            "type": "string",
            "pattern": "^ch_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "status": {
            "type": "string",
            "enum": [
              "present",
              "absent"
            ]
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ThreadArchiveResponse": {
        "type": "object",
        "required": [
          "thread_ids",
          "thread_in_channels"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "thread_in_channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          }
        }
      },
      "ThreadSnoozeResponse": {
        "type": "object",
        "required": [
          "snoozed_thread_ids",
          "thread_in_channels"
        ],
        "properties": {
          "snoozed_thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "thread_in_channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          }
        }
      },
      "ThreadMoveResponse": {
        "type": "object",
        "required": [
          "thread_ids",
          "thread_in_channels"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          },
          "thread_in_channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          }
        }
      },
      "ThreadMuteResponse": {
        "type": "object",
        "required": [
          "thread_ids"
        ],
        "properties": {
          "thread_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^th_.+"
            }
          }
        }
      },
      "ThreadMarkReadResponse": {
        "type": "object",
        "required": [
          "thread_id",
          "message_id"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          }
        }
      },
      "WebhookThreadCreateData": {
        "type": "object",
        "required": [
          "thread",
          "message"
        ],
        "properties": {
          "thread": {
            "$ref": "#/components/schemas/Thread"
          },
          "message": {
            "$ref": "#/components/schemas/MessageSummary"
          },
          "thread_in_channels": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadInChannel"
            }
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "WebhookMessageUpdatedData": {
        "type": "object",
        "required": [
          "message",
          "thread"
        ],
        "properties": {
          "message": {
            "$ref": "#/components/schemas/MessageSummary"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          }
        }
      },
      "WebhookMessageDeletedData": {
        "type": "object",
        "required": [
          "message_id",
          "thread",
          "deleted_at"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookMessageReactionCreatedData": {
        "type": "object",
        "required": [
          "message_id",
          "thread_id",
          "user_id",
          "name",
          "created_at"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "name": {
            "type": "string"
          },
          "variant": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookMessageReactionDeletedData": {
        "type": "object",
        "required": [
          "message_id",
          "thread_id",
          "user_id",
          "name"
        ],
        "properties": {
          "message_id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "WebhookThreadArchivedData": {
        "type": "object",
        "required": [
          "thread_id",
          "archived_at"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "archived_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookThreadSnoozedData": {
        "type": "object",
        "required": [
          "thread_id",
          "snoozed_at",
          "snoozed_until"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "snoozed_at": {
            "type": "string",
            "format": "date-time"
          },
          "snoozed_until": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookThreadMovedData": {
        "type": "object",
        "required": [
          "thread_id",
          "moved_at",
          "from_channel_id",
          "to_channel_id"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "moved_at": {
            "type": "string",
            "format": "date-time"
          },
          "from_channel_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ch_.+"
          },
          "to_channel_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^ch_.+"
          }
        }
      },
      "WebhookThreadMarkReadData": {
        "type": "object",
        "required": [
          "thread_id",
          "message_id",
          "user_id",
          "read_at"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "read_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookThreadLeftData": {
        "type": "object",
        "required": [
          "thread_id",
          "user_ids",
          "left_at"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^u_.+"
            }
          },
          "left_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookChannelCreatedData": {
        "type": "object",
        "required": [
          "channel"
        ],
        "properties": {
          "channel": {
            "type": "object",
            "required": [
              "id",
              "object",
              "name"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^ch_.+"
              },
              "object": {
                "type": "string",
                "enum": [
                  "channel"
                ]
              },
              "name": {
                "type": "string"
              }
            }
          }
        }
      },
      "WebhookAttachmentCreatedData": {
        "type": "object",
        "required": [
          "attachment"
        ],
        "properties": {
          "attachment": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^att_.+"
              },
              "object": {
                "type": "string",
                "enum": [
                  "attachment"
                ]
              },
              "upload_url": {
                "type": "string",
                "format": "uri",
                "description": "Signed URL to upload the file to."
              }
            }
          }
        }
      },
      "WebhookEventData": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/WebhookThreadCreateData"
          },
          {
            "$ref": "#/components/schemas/WebhookMessageUpdatedData"
          },
          {
            "$ref": "#/components/schemas/WebhookMessageDeletedData"
          },
          {
            "$ref": "#/components/schemas/WebhookMessageReactionCreatedData"
          },
          {
            "$ref": "#/components/schemas/WebhookMessageReactionDeletedData"
          },
          {
            "$ref": "#/components/schemas/WebhookThreadArchivedData"
          },
          {
            "$ref": "#/components/schemas/WebhookThreadSnoozedData"
          },
          {
            "$ref": "#/components/schemas/WebhookThreadMovedData"
          },
          {
            "$ref": "#/components/schemas/WebhookThreadMarkReadData"
          },
          {
            "$ref": "#/components/schemas/WebhookThreadLeftData"
          },
          {
            "$ref": "#/components/schemas/WebhookChannelCreatedData"
          },
          {
            "$ref": "#/components/schemas/WebhookAttachmentCreatedData"
          }
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^evt_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "event"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "thread.created",
              "message.created",
              "channel.created",
              "attachment.created",
              "thread.archived",
              "thread.snoozed",
              "thread.moved",
              "thread.mark_read",
              "thread.left",
              "message.updated",
              "message.deleted",
              "message.reaction.created",
              "message.reaction.deleted"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "$ref": "#/components/schemas/WebhookEventData"
          }
        }
      },
      "ThreadUsersMutationResponse": {
        "type": "object",
        "required": [
          "thread"
        ],
        "properties": {
          "thread": {
            "$ref": "#/components/schemas/Thread"
          }
        },
        "description": "Updated thread after user/role mutation."
      },
      "ChannelIcon": {
        "type": "object",
        "description": "Optional channel icon metadata.",
        "properties": {
          "color": {
            "type": "string"
          },
          "emoji": {
            "type": "string"
          }
        }
      },
      "Channel": {
        "type": "object",
        "required": [
          "id",
          "object",
          "name",
          "role",
          "order",
          "deleted_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ch_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "channel"
            ]
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "description": "Channel type (`personal`) or system bucket (`inbox`, `snoozed`, `archive`).",
            "enum": [
              "inbox",
              "snoozed",
              "archive",
              "personal"
            ]
          },
          "order": {
            "type": "number",
            "description": "Sort order used by clients for channel listing."
          },
          "deleted_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "icon": {
            "$ref": "#/components/schemas/ChannelIcon"
          },
          "idempotency_key": {
            "type": "string"
          }
        }
      },
      "ChannelListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Channel"
                }
              }
            }
          }
        ]
      },
      "Integration": {
        "type": "object",
        "required": [
          "id",
          "object",
          "name",
          "status",
          "type",
          "token_last_four",
          "webhook_url",
          "last_ip",
          "email",
          "last_used_at",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^int_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "integration"
            ]
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "revoked"
            ]
          },
          "type": {
            "type": "string",
            "description": "A personal token acting as the creator, or a bot with its own user.",
            "enum": [
              "personal_token",
              "bot"
            ]
          },
          "token_last_four": {
            "type": "string",
            "description": "Last four characters of the token, for identifying the credential."
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_ip": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": "string",
            "description": "Email of the user the integration acts as."
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "avatar_small_path": {
            "type": "string",
            "description": "Relative path to the bot's small avatar. Present only for bots with an avatar."
          },
          "avatar_large_path": {
            "type": "string",
            "description": "Relative path to the bot's large avatar. Present only for bots with an avatar."
          }
        }
      },
      "IntegrationListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          }
        ]
      },
      "IntegrationResponse": {
        "type": "object",
        "required": [
          "integration"
        ],
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/Integration"
          }
        }
      },
      "IntegrationCreatePayload": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Whether the integration acts as the creator or as its own bot user.",
            "enum": [
              "personal_token",
              "bot"
            ],
            "default": "personal_token"
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "IntegrationCreateRequest": {
        "type": "object",
        "required": [
          "integration"
        ],
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/IntegrationCreatePayload"
          }
        }
      },
      "IntegrationCreateResponse": {
        "type": "object",
        "required": [
          "integration",
          "token"
        ],
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/Integration"
          },
          "token": {
            "type": "string",
            "description": "Plaintext token, returned only once at creation."
          },
          "webhook_signing_secret": {
            "type": "string",
            "description": "Webhook signing secret, returned only once when a webhook_url is set."
          }
        }
      },
      "IntegrationUpdatePayload": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "IntegrationUpdateRequest": {
        "type": "object",
        "required": [
          "integration"
        ],
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/IntegrationUpdatePayload"
          }
        }
      },
      "IntegrationUpdateResponse": {
        "type": "object",
        "required": [
          "integration"
        ],
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/Integration"
          },
          "webhook_signing_secret": {
            "type": "string",
            "description": "Webhook signing secret, returned only when a webhook_url is first set."
          }
        }
      },
      "IntegrationAvatarUpload": {
        "type": "object",
        "required": [
          "avatar_file"
        ],
        "properties": {
          "avatar_file": {
            "type": "string",
            "format": "binary",
            "description": "Image file to use as the bot avatar."
          }
        }
      },
      "ChannelCreatePayload": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "order": {
            "type": "number"
          },
          "icon": {
            "$ref": "#/components/schemas/ChannelIcon"
          }
        }
      },
      "ChannelUpdatePayload": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "order": {
            "type": "number"
          },
          "icon": {
            "$ref": "#/components/schemas/ChannelIcon"
          }
        }
      },
      "ChannelCreateRequest": {
        "type": "object",
        "required": [
          "channel"
        ],
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/ChannelCreatePayload"
          }
        }
      },
      "ChannelUpdateRequest": {
        "type": "object",
        "required": [
          "channel"
        ],
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/ChannelUpdatePayload"
          }
        }
      },
      "ChannelCreateResponse": {
        "type": "object",
        "required": [
          "channel"
        ],
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/Channel"
          }
        }
      },
      "ChannelUpdateResponse": {
        "type": "object",
        "required": [
          "channel"
        ],
        "properties": {
          "channel": {
            "$ref": "#/components/schemas/Channel"
          }
        }
      },
      "ChannelDeleteResponse": {
        "type": "object",
        "required": [
          "channel_id",
          "deleted_at"
        ],
        "properties": {
          "channel_id": {
            "type": "string",
            "pattern": "^ch_.+"
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ScheduledMessageContent": {
        "type": "object",
        "required": [
          "id",
          "body"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "body": {
            "type": "string"
          },
          "reply_to": {
            "type": "string",
            "pattern": "^m_.+"
          },
          "attributes": {
            "type": "object",
            "additionalProperties": true
          },
          "attachments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MessageAttachment"
            }
          }
        }
      },
      "ScheduledMessage": {
        "type": "object",
        "required": [
          "id",
          "object",
          "thread_id",
          "user_id",
          "scheduled_at",
          "created_at",
          "updated_at",
          "message"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^sm_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "scheduled_message"
            ]
          },
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "message": {
            "$ref": "#/components/schemas/ScheduledMessageContent"
          }
        }
      },
      "ScheduledMessageCreateRequest": {
        "type": "object",
        "required": [
          "thread_id",
          "scheduled_at",
          "message"
        ],
        "properties": {
          "thread_id": {
            "type": "string",
            "pattern": "^th_.+"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "description": "Must be at least 1 minute in the future."
          },
          "message": {
            "type": "object",
            "description": "`body` is required unless `attachments` are provided.\n",
            "properties": {
              "body": {
                "type": "string"
              },
              "reply_to": {
                "type": "string",
                "pattern": "^m_.+",
                "description": "Prefixed message id to reply to."
              },
              "attributes": {
                "type": "object",
                "additionalProperties": true
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "pattern": "^att_.+"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ScheduledMessageUpdateRequest": {
        "type": "object",
        "description": "At least one of `scheduled_at` or `message` must be provided.",
        "properties": {
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "description": "Must be at least 1 minute in the future."
          },
          "message": {
            "type": "object",
            "properties": {
              "body": {
                "type": "string"
              },
              "reply_to": {
                "type": "string",
                "pattern": "^m_.+"
              },
              "attributes": {
                "type": "object",
                "additionalProperties": true
              },
              "attachments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "id"
                  ],
                  "properties": {
                    "id": {
                      "type": "string",
                      "pattern": "^att_.+"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ScheduledMessageResponse": {
        "type": "object",
        "required": [
          "scheduled_message"
        ],
        "properties": {
          "scheduled_message": {
            "$ref": "#/components/schemas/ScheduledMessage"
          }
        }
      },
      "ScheduledMessageListResponse": {
        "type": "object",
        "required": [
          "scheduled_messages"
        ],
        "properties": {
          "scheduled_messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduledMessage"
            }
          }
        }
      },
      "ScheduledMessageDeleteResponse": {
        "type": "object",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^sm_.+"
          }
        }
      },
      "ScheduledMessageSendResponse": {
        "type": "object",
        "required": [
          "id",
          "message",
          "thread"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^sm_.+"
          },
          "message": {
            "$ref": "#/components/schemas/Message"
          },
          "thread": {
            "$ref": "#/components/schemas/Thread"
          }
        }
      },
      "Attachment": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "key",
          "status",
          "user_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^att_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "attachment"
            ]
          },
          "type": {
            "type": "string"
          },
          "filename": {
            "type": [
              "string",
              "null"
            ]
          },
          "content_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "key": {
            "type": "string"
          },
          "preview_key": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "finished"
            ]
          },
          "user_id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "thread_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^th_.+"
          },
          "message_id": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^m_.+"
          },
          "width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "preview_size": {
            "type": [
              "integer",
              "null"
            ]
          },
          "preview_width": {
            "type": [
              "integer",
              "null"
            ]
          },
          "preview_height": {
            "type": [
              "integer",
              "null"
            ]
          },
          "preview_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending",
              "finished",
              null
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "idempotency_key": {
            "type": "string"
          }
        }
      },
      "AttachmentCreateRequest": {
        "description": "Attachment create request, accepts flat or nested payload shape.",
        "oneOf": [
          {
            "type": "object",
            "required": [
              "filename",
              "size"
            ],
            "properties": {
              "filename": {
                "type": "string",
                "description": "Original filename presented to BirdyChat users."
              },
              "content_type": {
                "type": "string",
                "description": "MIME type of the uploaded file, for example `application/pdf`."
              },
              "size": {
                "type": "integer",
                "description": "Size of the original uploaded file in bytes."
              },
              "thread_id": {
                "type": "string",
                "pattern": "^th_.+",
                "description": "Optional thread to associate with the attachment metadata."
              },
              "preview_size": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Optional preview object size in bytes, if a preview will also be uploaded."
              }
            }
          },
          {
            "type": "object",
            "required": [
              "attachment"
            ],
            "properties": {
              "attachment": {
                "type": "object",
                "required": [
                  "filename",
                  "size"
                ],
                "properties": {
                  "filename": {
                    "type": "string",
                    "description": "Original filename presented to BirdyChat users."
                  },
                  "content_type": {
                    "type": "string",
                    "description": "MIME type of the uploaded file, for example `application/pdf`."
                  },
                  "size": {
                    "type": "integer",
                    "description": "Size of the original uploaded file in bytes."
                  },
                  "thread_id": {
                    "type": "string",
                    "pattern": "^th_.+",
                    "description": "Optional thread to associate with the attachment metadata."
                  },
                  "preview_size": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Optional preview object size in bytes, if a preview will also be uploaded."
                  }
                }
              }
            }
          }
        ]
      },
      "AttachmentCreatePayload": {
        "type": "object",
        "required": [
          "id",
          "upload_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^att_.+"
          },
          "upload_url": {
            "type": "string",
            "format": "uri",
            "description": "Signed URL to upload the file to. POST the file as multipart/form-data\nwith a `file` field. Maximum file size is 10 MB.\n"
          }
        }
      },
      "AttachmentCreateResponse": {
        "type": "object",
        "required": [
          "attachment"
        ],
        "properties": {
          "attachment": {
            "$ref": "#/components/schemas/AttachmentCreatePayload"
          }
        }
      },
      "AttachmentDeleteResponse": {
        "type": "object",
        "required": [
          "attachment_id"
        ],
        "properties": {
          "attachment_id": {
            "type": "string",
            "pattern": "^att_.+"
          }
        }
      },
      "UserProfile": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "company": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "about_me": {
            "type": "string"
          }
        }
      },
      "User": {
        "type": "object",
        "required": [
          "id",
          "object",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^u_.+"
          },
          "object": {
            "type": "string",
            "enum": [
              "user"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "time_zone": {
            "type": [
              "string",
              "null"
            ]
          },
          "avatar_small_path": {
            "type": "string"
          },
          "avatar_small_url": {
            "type": "string"
          },
          "avatar_large_path": {
            "type": "string"
          },
          "roles": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bot"
              ]
            },
            "description": "Public roles assigned to this user. Only present when the user has at least one public role."
          },
          "profile": {
            "$ref": "#/components/schemas/UserProfile"
          }
        }
      },
      "UserListResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ListMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          }
        ]
      },
      "Error": {
        "type": "object",
        "required": [
          "type",
          "code",
          "message"
        ],
        "properties": {
          "type": {
            "type": "string",
            "example": "invalid_request_error"
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code.\nExamples of currently documented values include `forbidden`,\n`invalid_channel_id`, `invalid_json`, `invalid_message`, `invalid_message_id`,\n`invalid_params`, `invalid_scheduled_at`, `invalid_scheduled_message_id`,\n`invalid_thread_id`, `limit_exceeded`, `missing_message`, `missing_thread_id`,\n`not_authenticated`, `not_found`, and `permission_denied`.\n",
            "example": "missing_message_id"
          },
          "message": {
            "type": "string",
            "example": "The message_id parameter is required and must be m_ prefixed"
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "$ref": "#/components/schemas/Error"
          }
        }
      },
      "ErrorTopLevel": {
        "type": "object",
        "required": [
          "type",
          "code",
          "message"
        ],
        "properties": {
          "type": {
            "type": "string",
            "example": "invalid_request_error"
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code.\nExamples of currently documented values include `forbidden`,\n`invalid_channel_id`, `invalid_json`, `invalid_message`, `invalid_message_id`,\n`invalid_params`, `invalid_scheduled_at`, `invalid_scheduled_message_id`,\n`invalid_thread_id`, `limit_exceeded`, `missing_message`, `missing_thread_id`,\n`not_authenticated`, `not_found`, and `permission_denied`.\n",
            "example": "not_authenticated"
          },
          "message": {
            "type": "string",
            "example": "Request is not authenticated"
          }
        }
      },
      "MessageOnlyError": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string",
            "example": "Not found"
          }
        }
      },
      "InvalidJsonError": {
        "type": "object",
        "required": [
          "success",
          "object",
          "error"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "const": false
          },
          "object": {
            "type": "string",
            "const": "error"
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "const": "invalid_json"
              },
              "message": {
                "type": "string",
                "example": "Malformed JSON request body"
              }
            }
          }
        }
      },
      "ErrorResponse": {
        "description": "API currently returns multiple error payload shapes.\nMost endpoints use `error` envelope payloads, auth failures use top-level\n`type/code/message`, and some legacy paths return a top-level `message`.\n",
        "oneOf": [
          {
            "$ref": "#/components/schemas/ErrorEnvelope"
          },
          {
            "$ref": "#/components/schemas/ErrorTopLevel"
          },
          {
            "$ref": "#/components/schemas/MessageOnlyError"
          },
          {
            "$ref": "#/components/schemas/InvalidJsonError"
          }
        ]
      },
      "ListMeta": {
        "type": "object",
        "required": [
          "object",
          "has_more"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "list"
            ]
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "prev_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "responses": {
      "Forbidden": {
        "description": "Request is authenticated but not allowed for this resource (permission or mutability constraint).",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "forbidden": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "forbidden",
                    "message": "Request is not allowed for this resource"
                  }
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Requested resource is not found or not visible in current scope.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "notFound": {
                "value": {
                  "error": {
                    "type": "invalid_request_error",
                    "code": "not_found",
                    "message": "Resource not found"
                  }
                }
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Request is not authenticated.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "notAuthenticated": {
                "value": {
                  "type": "invalid_request_error",
                  "code": "not_authenticated",
                  "message": "Request is not authenticated"
                }
              }
            }
          }
        }
      },
      "BadRequest": {
        "description": "Bad request payload or malformed JSON.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "invalidJson": {
                "value": {
                  "success": false,
                  "object": "error",
                  "error": {
                    "code": "invalid_json",
                    "message": "Malformed JSON request body"
                  }
                }
              }
            }
          }
        }
      },
      "RateLimit": {
        "description": "Request was rate limited.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "limitExceeded": {
                "value": {
                  "error": {
                    "type": "rate_limit",
                    "code": "limit_exceeded",
                    "message": "Rate limit exceeded"
                  }
                }
              }
            }
          }
        }
      },
      "NotFoundMessageOnly": {
        "description": "Requested resource is not found.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/MessageOnlyError"
            },
            "examples": {
              "notFound": {
                "value": {
                  "message": "Not found"
                }
              }
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Validation failed for the request payload.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "invalidPayload": {
                "value": {
                  "error": {
                    "message": "Validation failed"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Core Messaging",
      "tags": [
        "Threads",
        "Messages",
        "Scheduled Messages",
        "Channels",
        "Users",
        "Events"
      ]
    },
    {
      "name": "File Handling",
      "tags": [
        "Attachments"
      ]
    },
    {
      "name": "Integrations & Webhooks",
      "tags": [
        "Integrations",
        "Webhooks"
      ]
    }
  ]
}