{
  "openapi": "3.1.0",
  "info": {
    "title": "Rookery API",
    "version": "1.0.0",
    "summary": "Work in a Rookery inbox from your own apps and agents.",
    "description": "The Rookery API lets your app or agent work in your inbox as a teammate: read conversations, add notes, tag and assign, and draft replies a person approves. The same operations are tools on the MCP server at /mcp.\n\nEvery request needs an API key from **Settings → Integrations → API keys**, sent as `Authorization: Bearer rk_…`. Each key acts as its own agent, sees what the person who made it can see, and does only what its scopes allow.",
    "contact": {
      "name": "Rookery",
      "email": "hello@userookery.com",
      "url": "https://userookery.com/developers/"
    }
  },
  "externalDocs": {
    "description": "Guides and reference",
    "url": "https://userookery.com/developers/"
  },
  "servers": [
    {
      "url": "https://app.userookery.com/api/v1"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "tags": [
    {
      "name": "Your key",
      "description": "Check which agent a key acts as, and what it may do."
    },
    {
      "name": "Conversations",
      "description": "Find, read and work on conversations: notes, status, tags and assignment."
    },
    {
      "name": "Replies",
      "description": "Write to the customer. Replies are drafts for a person to approve unless the key may send."
    },
    {
      "name": "Workspace",
      "description": "The inboxes and tags in this workspace."
    },
    {
      "name": "Documents",
      "description": "The document library: invoices, receipts, contracts and other files, with what Fetch read from them."
    },
    {
      "name": "Webhook events",
      "description": "What Rookery POSTs to your webhook when something happens."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "get_me",
        "summary": "Check your key",
        "description": "Returns the agent this key acts as and the scopes it has. A quick way to check a key works.",
        "tags": [
          "Your key"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "agent": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "description": "The agent's id, like `agt_…`."
                        },
                        "name": {
                          "type": "string",
                          "description": "The key's name."
                        }
                      },
                      "required": [
                        "id",
                        "name"
                      ]
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "enum": [
                          "read",
                          "write",
                          "draft",
                          "send"
                        ]
                      }
                    }
                  },
                  "required": [
                    "agent",
                    "scopes"
                  ]
                },
                "example": {
                  "agent": {
                    "id": "agt_3n7q2wv9k4hxm8tr",
                    "name": "Support bot"
                  },
                  "scopes": [
                    "read",
                    "draft"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": null,
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/me' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/me\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/me\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations": {
      "get": {
        "operationId": "list_conversations",
        "summary": "List conversations",
        "description": "Lists conversations, newest first. Use `view` for open, waiting, snoozed or closed; `query` searches all mail text.\n\nYou only see what the person who made the key can see: every team inbox, plus their own private inboxes.\n\nResults are newest first, up to `limit` (at most 100). There's no cursor yet: narrow the list with `view`, `mailbox` or `q`.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "view",
            "in": "query",
            "required": false,
            "description": "Which conversations to list. `waiting` means waiting on the customer.",
            "schema": {
              "default": "open",
              "type": "string",
              "enum": [
                "open",
                "waiting",
                "snoozed",
                "closed"
              ]
            },
            "example": "open"
          },
          {
            "name": "mailbox",
            "in": "query",
            "required": false,
            "description": "A mailbox id from list_mailboxes.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Full-text search.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "assigned",
            "in": "query",
            "required": false,
            "description": "`me` means assigned to this agent.",
            "schema": {
              "type": "string",
              "enum": [
                "me",
                "unassigned"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, newest first.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The conversation's id, like `cnv_…`."
                      },
                      "subject": {
                        "type": "string"
                      },
                      "snippet": {
                        "type": "string",
                        "description": "The start of the latest message."
                      },
                      "status": {
                        "type": "string",
                        "enum": [
                          "open",
                          "waiting",
                          "closed"
                        ]
                      },
                      "contact": {
                        "type": "object",
                        "properties": {
                          "name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "email": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "name",
                          "email"
                        ],
                        "description": "The customer the conversation is with."
                      },
                      "mailbox": {
                        "type": "string",
                        "description": "The inbox's name."
                      },
                      "lastMessageAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "ISO 8601, UTC."
                      },
                      "messageCount": {
                        "type": "integer"
                      },
                      "assignee": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "A `usr_…` or `agt_…` id."
                              },
                              "name": {
                                "type": "string"
                              },
                              "type": {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "agent"
                                ]
                              }
                            },
                            "required": [
                              "id",
                              "name",
                              "type"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Who the conversation is assigned to, or null."
                      },
                      "tags": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      },
                      "topic": {
                        "description": "The topic Scout sorted it under, or null.",
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "urgency": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "low",
                              "normal",
                              "high"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Set by Scout when it sorts new mail."
                      },
                      "risk": {
                        "description": "Scout's warning, like `phishing`, or null when nothing looks wrong.",
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    },
                    "required": [
                      "id",
                      "subject",
                      "snippet",
                      "status",
                      "contact",
                      "mailbox",
                      "lastMessageAt",
                      "messageCount",
                      "assignee",
                      "tags",
                      "topic",
                      "urgency",
                      "risk"
                    ]
                  }
                },
                "example": [
                  {
                    "id": "cnv_8k2m4q7rx9tbw3hd",
                    "subject": "Where is my order?",
                    "snippet": "Order 4502 hasn't arrived and the tracking hasn't moved since Monday.",
                    "status": "open",
                    "contact": {
                      "name": "Lee Park",
                      "email": "lee@example.com"
                    },
                    "mailbox": "Support",
                    "lastMessageAt": "2026-10-09T14:32:05.000Z",
                    "messageCount": 2,
                    "assignee": null,
                    "tags": [
                      "shipping"
                    ],
                    "topic": "order status",
                    "urgency": "normal",
                    "risk": null
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "list_conversations",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/conversations?view=open&limit=1' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations?view=open&limit=1\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/conversations\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    params={\n        \"view\": \"open\",\n        \"limit\": 1,\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}": {
      "get": {
        "operationId": "get_conversation",
        "summary": "Read a conversation",
        "description": "Reads a conversation: messages (quoted history removed), internal notes, events, tags and who's on the team.\n\nThe timeline is oldest first and mixes three kinds of item: `message`, `note` and `event`. Message text is plain text, with quoted history removed and anything past 8,000 characters cut.\n\n`team` lists the people and agents you can assign it to, with the ids `assign_conversation` takes.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The conversation's id, like `cnv_…`."
                    },
                    "subject": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "open",
                        "waiting",
                        "closed"
                      ]
                    },
                    "mailbox": {
                      "type": "string",
                      "description": "The inbox's address."
                    },
                    "contact": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "email": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "name",
                        "email"
                      ],
                      "description": "The customer the conversation is with."
                    },
                    "assignee": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "A `usr_…` or `agt_…` id."
                            },
                            "name": {
                              "type": "string"
                            },
                            "type": {
                              "type": "string",
                              "enum": [
                                "user",
                                "agent"
                              ]
                            }
                          },
                          "required": [
                            "id",
                            "name",
                            "type"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Who the conversation is assigned to, or null."
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "topic": {
                      "description": "The topic Scout sorted it under, or null.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "urgency": {
                      "anyOf": [
                        {
                          "type": "string",
                          "enum": [
                            "low",
                            "normal",
                            "high"
                          ]
                        },
                        {
                          "type": "null"
                        }
                      ],
                      "description": "Set by Scout when it sorts new mail."
                    },
                    "risk": {
                      "description": "Scout's warning, like `phishing`, or null when nothing looks wrong.",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "riskReasons": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "Up to three plain reasons for `risk`."
                    },
                    "snoozedUntil": {
                      "anyOf": [
                        {
                          "type": "string",
                          "format": "date-time",
                          "description": "ISO 8601, UTC."
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "timeline": {
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "const": "message"
                              },
                              "id": {
                                "type": "string",
                                "description": "The message's id, like `msg_…`."
                              },
                              "at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "ISO 8601, UTC."
                              },
                              "direction": {
                                "type": "string",
                                "enum": [
                                  "inbound",
                                  "outbound"
                                ]
                              },
                              "from": {
                                "type": "object",
                                "properties": {
                                  "name": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "email": {
                                    "type": "string"
                                  }
                                },
                                "required": [
                                  "name",
                                  "email"
                                ]
                              },
                              "status": {
                                "anyOf": [
                                  {
                                    "type": "string",
                                    "enum": [
                                      "draft",
                                      "scheduled",
                                      "sending",
                                      "sent",
                                      "failed"
                                    ]
                                  },
                                  {
                                    "type": "null"
                                  }
                                ],
                                "description": "For replies: where it stands. Null for mail that came in."
                              },
                              "text": {
                                "type": "string"
                              },
                              "attachments": {
                                "type": "array",
                                "items": {
                                  "type": "object",
                                  "properties": {
                                    "filename": {
                                      "type": "string"
                                    },
                                    "contentType": {
                                      "type": "string"
                                    },
                                    "size": {
                                      "type": "integer"
                                    }
                                  },
                                  "required": [
                                    "filename",
                                    "contentType",
                                    "size"
                                  ]
                                }
                              }
                            },
                            "required": [
                              "type",
                              "id",
                              "at",
                              "direction",
                              "from",
                              "status",
                              "text",
                              "attachments"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "const": "note"
                              },
                              "id": {
                                "type": "string"
                              },
                              "at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "ISO 8601, UTC."
                              },
                              "author": {
                                "type": "string"
                              },
                              "body": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "type",
                              "id",
                              "at",
                              "author",
                              "body"
                            ]
                          },
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "const": "event"
                              },
                              "at": {
                                "type": "string",
                                "format": "date-time",
                                "description": "ISO 8601, UTC."
                              },
                              "actor": {
                                "type": "string"
                              },
                              "event": {
                                "type": "string",
                                "description": "What happened, like `assigned` or `status`."
                              },
                              "data": {
                                "type": "object",
                                "propertyNames": {
                                  "type": "string"
                                },
                                "additionalProperties": {}
                              }
                            },
                            "required": [
                              "type",
                              "at",
                              "actor",
                              "event",
                              "data"
                            ]
                          }
                        ]
                      }
                    },
                    "team": {
                      "type": "object",
                      "properties": {
                        "people": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "`user:usr_…`"
                              },
                              "name": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ]
                          }
                        },
                        "agents": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "id": {
                                "type": "string",
                                "description": "`agent:agt_…`"
                              },
                              "name": {
                                "type": "string"
                              }
                            },
                            "required": [
                              "id",
                              "name"
                            ]
                          }
                        }
                      },
                      "required": [
                        "people",
                        "agents"
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "subject",
                    "status",
                    "mailbox",
                    "contact",
                    "assignee",
                    "tags",
                    "topic",
                    "urgency",
                    "risk",
                    "riskReasons",
                    "snoozedUntil",
                    "timeline",
                    "team"
                  ]
                },
                "example": {
                  "id": "cnv_8k2m4q7rx9tbw3hd",
                  "subject": "Where is my order?",
                  "status": "open",
                  "mailbox": "help@yourshop.com",
                  "contact": {
                    "name": "Lee Park",
                    "email": "lee@example.com"
                  },
                  "assignee": null,
                  "tags": [
                    "shipping"
                  ],
                  "topic": "order status",
                  "urgency": "normal",
                  "risk": null,
                  "riskReasons": [],
                  "snoozedUntil": null,
                  "timeline": [
                    {
                      "type": "message",
                      "id": "msg_5d9w2k7hq3mx8rtn",
                      "at": "2026-10-09T14:32:05.000Z",
                      "direction": "inbound",
                      "from": {
                        "name": "Lee Park",
                        "email": "lee@example.com"
                      },
                      "status": null,
                      "text": "Order 4502 hasn't arrived and the tracking hasn't moved since Monday.",
                      "attachments": []
                    },
                    {
                      "type": "note",
                      "id": "not_2h8q4w7m9kx3drtb",
                      "at": "2026-10-09T14:40:11.000Z",
                      "author": "Jess",
                      "body": "Carrier says it's at the depot. @Sam can you check?"
                    }
                  ],
                  "team": {
                    "people": [
                      {
                        "id": "user:usr_4k8m2q9wx7hd3rtn",
                        "name": "Jess"
                      }
                    ],
                    "agents": [
                      {
                        "id": "agent:agt_3n7q2wv9k4hxm8tr",
                        "name": "Support bot"
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "get_conversation",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/notes": {
      "post": {
        "operationId": "add_note",
        "summary": "Add an internal note",
        "description": "Adds an internal note the team sees and the customer never does. Mention people with @FirstName.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 10000,
                    "description": "The note, as plain text."
                  }
                },
                "required": [
                  "body"
                ]
              },
              "example": {
                "body": "Tracking shows it's at the depot. @Jess can you call the carrier?"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `write` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "write"
        ],
        "x-rookery-idempotent": false,
        "x-rookery-mcp-tool": "add_note",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/notes \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"body\": \"Tracking shows it'\\''s at the depot. @Jess can you call the carrier?\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/notes\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"body\": \"Tracking shows it's at the depot. @Jess can you call the carrier?\"\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/notes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"body\": \"Tracking shows it's at the depot. @Jess can you call the carrier?\",\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/status": {
      "post": {
        "operationId": "set_status",
        "summary": "Change status",
        "description": "Sets a conversation to open, waiting (on the customer) or closed.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "waiting",
                      "closed"
                    ],
                    "description": "The new status. `waiting` means waiting on the customer."
                  }
                },
                "required": [
                  "status"
                ]
              },
              "example": {
                "status": "waiting"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `write` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "write"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "set_status",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/status \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"status\": \"waiting\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/status\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"status\": \"waiting\"\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/status\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"status\": \"waiting\",\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/tags": {
      "post": {
        "operationId": "tag_conversation",
        "summary": "Tag or untag",
        "description": "Adds tags to a conversation, or removes them. New tag names are created.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "add": {
                    "default": [],
                    "description": "Tag names to add.",
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    }
                  },
                  "remove": {
                    "default": [],
                    "description": "Tag names to remove.",
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 40
                    }
                  }
                }
              },
              "example": {
                "add": [
                  "vip"
                ],
                "remove": [
                  "new"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `write` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "write"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "tag_conversation",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/tags \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"add\": [\n    \"vip\"\n  ],\n  \"remove\": [\n    \"new\"\n  ]\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/tags\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"add\": [\n      \"vip\"\n    ],\n    \"remove\": [\n      \"new\"\n    ]\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/tags\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"add\": [\n            \"vip\",\n        ],\n        \"remove\": [\n            \"new\",\n        ],\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/assign": {
      "post": {
        "operationId": "assign_conversation",
        "summary": "Assign",
        "description": "Assigns a conversation to a person or agent (ids like user:… or agent:… from get_conversation's team), to yourself with `me`, or unassigns with `none`.",
        "tags": [
          "Conversations"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 80,
                    "description": "`user:usr_…`, `agent:agt_…`, `me` or `none`."
                  }
                },
                "required": [
                  "to"
                ]
              },
              "example": {
                "to": "user:usr_4k8m2q9wx7hd3rtn"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "ok"
                  ]
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field. Or: The person or agent isn't on the team, or can't see this inbox.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `write` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "write"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "assign_conversation",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/assign \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"to\": \"user:usr_4k8m2q9wx7hd3rtn\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/assign\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"to\": \"user:usr_4k8m2q9wx7hd3rtn\"\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/assign\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"to\": \"user:usr_4k8m2q9wx7hd3rtn\",\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/replies": {
      "post": {
        "operationId": "reply",
        "summary": "Reply to the customer",
        "description": "Writes a reply to the conversation's contact. With send: false (the default) it's a draft a person approves under Needs your yes. With send: true it goes out after a 10-minute undo window; that needs the `send` scope. To ask for documents, list them in `documents`: a private upload link and checklist go under the reply, and reminders follow. Don't write the link yourself.\n\nA draft lands in **Needs your yes**, next to Quill's, with your `summary` on top. Nothing reaches the customer until a person approves it.\n\nWith `send: true` the reply is scheduled and leaves after a 10-minute undo window, during which anyone on the team can stop it.",
        "tags": [
          "Replies"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50000,
                    "description": "The reply, as plain text."
                  },
                  "send": {
                    "default": false,
                    "description": "False (the default) makes a draft for a person to approve. True sends it, and needs the `send` scope.",
                    "type": "boolean"
                  },
                  "summary": {
                    "description": "One line for the person approving: what this reply does.",
                    "type": "string",
                    "maxLength": 500
                  },
                  "documents": {
                    "default": [],
                    "description": "Documents to ask the customer to upload.",
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120,
                          "description": "Short name, e.g. 'Proof of purchase'."
                        },
                        "description": {
                          "default": "",
                          "description": "What counts, in a sentence. Optional.",
                          "type": "string",
                          "maxLength": 500
                        },
                        "required": {
                          "default": true,
                          "description": "False marks it as nice to have.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "label"
                      ]
                    }
                  }
                },
                "required": [
                  "body"
                ]
              },
              "example": {
                "body": "Hi Lee, thanks for your patience. Your parcel is at the local depot and should reach you tomorrow.",
                "send": false,
                "summary": "Tells Lee the parcel arrives tomorrow"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messageId": {
                      "type": "string",
                      "description": "The message's id, like `msg_…`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "scheduled"
                      ],
                      "description": "`draft` waits for a person's yes; `scheduled` goes out on its own."
                    },
                    "sendsAt": {
                      "description": "When a sent reply leaves, after the 10-minute undo window.",
                      "type": "string",
                      "format": "date-time"
                    },
                    "requestId": {
                      "type": "string",
                      "description": "The document request's id, like `req_…`."
                    },
                    "note": {
                      "description": "What happens next, in a sentence.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "messageId",
                    "status"
                  ]
                },
                "example": {
                  "messageId": "msg_7r3k9w2hq8mx4dtn",
                  "status": "draft",
                  "note": "Waiting for a person to approve it."
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `draft` scope (or `send`, to send).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "draft",
          "send"
        ],
        "x-rookery-idempotent": false,
        "x-rookery-mcp-tool": "reply",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {
            "send": false
          },
          "note": "Sending is off in Try it. Use the sandbox (coming soon) or your own code."
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/replies \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"body\": \"Hi Lee, thanks for your patience. Your parcel is at the local depot and should reach you tomorrow.\",\n  \"send\": false,\n  \"summary\": \"Tells Lee the parcel arrives tomorrow\"\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/replies\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"body\": \"Hi Lee, thanks for your patience. Your parcel is at the local depot and should reach you tomorrow.\",\n    \"send\": false,\n    \"summary\": \"Tells Lee the parcel arrives tomorrow\"\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/replies\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"body\": \"Hi Lee, thanks for your patience. Your parcel is at the local depot and should reach you tomorrow.\",\n        \"send\": False,\n        \"summary\": \"Tells Lee the parcel arrives tomorrow\",\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/conversations/{id}/document-requests": {
      "post": {
        "operationId": "request_documents",
        "summary": "Ask the customer for documents",
        "description": "Asks the conversation's contact to upload documents through a private page with a checklist; reminders follow on days 2, 4 and 7, and each upload is checked. A draft for approval by default; with send: true (needs the `send` scope) it goes out after a 10-minute undo window.",
        "tags": [
          "Replies"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The conversation's id, like `cnv_…`.",
            "schema": {
              "type": "string",
              "pattern": "^cnv_[0-9a-z]+$"
            },
            "example": "cnv_8k2m4q7rx9tbw3hd"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "documents": {
                    "minItems": 1,
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "label": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 120,
                          "description": "Short name, e.g. 'Proof of purchase'."
                        },
                        "description": {
                          "default": "",
                          "description": "What counts, in a sentence. Optional.",
                          "type": "string",
                          "maxLength": 500
                        },
                        "required": {
                          "default": true,
                          "description": "False marks it as nice to have.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "label"
                      ]
                    },
                    "description": "What to ask for: up to 20 items."
                  },
                  "message": {
                    "description": "A short note above the checklist. Greet the customer.",
                    "type": "string",
                    "maxLength": 5000
                  },
                  "dueDate": {
                    "description": "YYYY-MM-DD",
                    "type": "string",
                    "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
                  },
                  "send": {
                    "default": false,
                    "description": "False (the default) makes a draft for a person to approve. True sends it, and needs the `send` scope.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "documents"
                ]
              },
              "example": {
                "documents": [
                  {
                    "label": "Proof of purchase"
                  },
                  {
                    "label": "Photo of the damage",
                    "required": false
                  }
                ],
                "message": "Hi Lee, could you send these so we can sort out the refund?",
                "dueDate": "2026-11-01",
                "send": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "messageId": {
                      "type": "string",
                      "description": "The message's id, like `msg_…`."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "draft",
                        "scheduled"
                      ],
                      "description": "`draft` waits for a person's yes; `scheduled` goes out on its own."
                    },
                    "sendsAt": {
                      "description": "When a sent reply leaves, after the 10-minute undo window.",
                      "type": "string",
                      "format": "date-time"
                    },
                    "requestId": {
                      "type": "string",
                      "description": "The document request's id, like `req_…`."
                    },
                    "note": {
                      "description": "What happens next, in a sentence.",
                      "type": "string"
                    }
                  },
                  "required": [
                    "messageId",
                    "status"
                  ]
                },
                "example": {
                  "messageId": "msg_9q2w7k4hx3mr8dtb",
                  "status": "draft",
                  "note": "Waiting for a person to approve it. The upload link is added when it's approved."
                }
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `draft` scope (or `send`, to send).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "There's no such conversation, or the key can't see it (someone's private inbox).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "draft",
          "send"
        ],
        "x-rookery-idempotent": false,
        "x-rookery-mcp-tool": "request_documents",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {
            "send": false
          },
          "note": "Sending is off in Try it. Use the sandbox (coming soon) or your own code."
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl -X POST https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/document-requests \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n  \"documents\": [\n    {\n      \"label\": \"Proof of purchase\"\n    },\n    {\n      \"label\": \"Photo of the damage\",\n      \"required\": false\n    }\n  ],\n  \"message\": \"Hi Lee, could you send these so we can sort out the refund?\",\n  \"dueDate\": \"2026-11-01\",\n  \"send\": false\n}'"
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/document-requests\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.ROOKERY_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"documents\": [\n      {\n        \"label\": \"Proof of purchase\"\n      },\n      {\n        \"label\": \"Photo of the damage\",\n        \"required\": false\n      }\n    ],\n    \"message\": \"Hi Lee, could you send these so we can sort out the refund?\",\n    \"dueDate\": \"2026-11-01\",\n    \"send\": false\n  }),\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.post(\n    \"https://app.userookery.com/api/v1/conversations/cnv_8k2m4q7rx9tbw3hd/document-requests\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    json={\n        \"documents\": [\n            {\n                \"label\": \"Proof of purchase\",\n            },\n            {\n                \"label\": \"Photo of the damage\",\n                \"required\": False,\n            },\n        ],\n        \"message\": \"Hi Lee, could you send these so we can sort out the refund?\",\n        \"dueDate\": \"2026-11-01\",\n        \"send\": False,\n    },\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/mailboxes": {
      "get": {
        "operationId": "list_mailboxes",
        "summary": "List mailboxes",
        "description": "Lists the inboxes, with how many conversations are open in each.",
        "tags": [
          "Workspace"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The mailbox's id, like `mbx_…`."
                      },
                      "address": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "open": {
                        "type": "integer",
                        "description": "Open conversations."
                      }
                    },
                    "required": [
                      "id",
                      "address",
                      "name",
                      "open"
                    ]
                  }
                },
                "example": [
                  {
                    "id": "mbx_6t2k9q4wm8xh3drn",
                    "address": "help@yourshop.com",
                    "name": "Support",
                    "open": 12
                  }
                ]
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "list_mailboxes",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/mailboxes' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/mailboxes\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/mailboxes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/tags": {
      "get": {
        "operationId": "list_tags",
        "summary": "List tags",
        "description": "Lists the tags in use and how many conversations have each.",
        "tags": [
          "Workspace"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The tag's id, like `tag_…`."
                      },
                      "name": {
                        "type": "string"
                      },
                      "count": {
                        "type": "integer"
                      }
                    },
                    "required": [
                      "id",
                      "name",
                      "count"
                    ]
                  }
                },
                "example": [
                  {
                    "id": "tag_2m8k4q9wx3hd7rtn",
                    "name": "shipping",
                    "count": 18
                  },
                  {
                    "id": "tag_9w3k7q2hm4xd8rtb",
                    "name": "vip",
                    "count": 4
                  }
                ]
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "list_tags",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/tags' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/tags\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/tags\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n)\ndata = response.json()"
          }
        ]
      }
    },
    "/documents": {
      "get": {
        "operationId": "search_documents",
        "summary": "Search documents",
        "description": "Searches the document library: invoices, receipts, contracts and other files, with extracted fields.",
        "tags": [
          "Documents"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Words in the title, file name or fields.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "acme"
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Only this kind of document.",
            "schema": {
              "type": "string",
              "enum": [
                "invoice",
                "receipt",
                "statement",
                "contract",
                "id",
                "tax",
                "photo",
                "other"
              ]
            },
            "example": "invoice"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "How many to return, newest first.",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "The document's id, like `doc_…`."
                      },
                      "title": {
                        "type": "string",
                        "description": "A readable title, or the file name."
                      },
                      "filename": {
                        "type": "string"
                      },
                      "kind": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "invoice",
                              "receipt",
                              "statement",
                              "contract",
                              "id",
                              "tax",
                              "photo",
                              "other"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "fields": {
                        "type": "object",
                        "properties": {
                          "vendor": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "amount": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "currency": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "date": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "dueDate": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reference": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "description": "What Fetch read from it. Any of these can be missing."
                      },
                      "conversationId": {
                        "anyOf": [
                          {
                            "type": "string",
                            "description": "The conversation's id, like `cnv_…`."
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "createdAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "ISO 8601, UTC."
                      }
                    },
                    "required": [
                      "id",
                      "title",
                      "filename",
                      "kind",
                      "fields",
                      "conversationId",
                      "createdAt"
                    ]
                  }
                },
                "example": [
                  {
                    "id": "doc_4h8q2w9k7mx3drtn",
                    "title": "Acme Supplies invoice 1182",
                    "filename": "INV-1182.pdf",
                    "kind": "invoice",
                    "fields": {
                      "vendor": "Acme Supplies",
                      "amount": 412.5,
                      "currency": "USD",
                      "dueDate": "2026-10-30",
                      "reference": "1182"
                    },
                    "conversationId": "cnv_8k2m4q7rx9tbw3hd",
                    "createdAt": "2026-10-09T14:32:05.000Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Something in the request is missing or not allowed. The message says which field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No key, or the key is wrong or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key doesn't have the `read` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests in a minute with this key. Wait, then try again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "x-rookery-scopes": [
          "read"
        ],
        "x-rookery-idempotent": true,
        "x-rookery-mcp-tool": "search_documents",
        "x-rookery-try-it": {
          "allowed": true,
          "locked": {}
        },
        "x-codeSamples": [
          {
            "lang": "Shell",
            "label": "curl",
            "source": "curl 'https://app.userookery.com/api/v1/documents?q=acme&kind=invoice&limit=1' \\\n  -H \"Authorization: Bearer $ROOKERY_KEY\""
          },
          {
            "lang": "JavaScript",
            "label": "JavaScript",
            "source": "const response = await fetch(\"https://app.userookery.com/api/v1/documents?q=acme&kind=invoice&limit=1\", {\n  headers: { Authorization: `Bearer ${process.env.ROOKERY_KEY}` },\n});\nconst data = await response.json();"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresponse = requests.get(\n    \"https://app.userookery.com/api/v1/documents\",\n    headers={\"Authorization\": f\"Bearer {os.environ['ROOKERY_KEY']}\"},\n    params={\n        \"q\": \"acme\",\n        \"kind\": \"invoice\",\n        \"limit\": 1,\n    },\n)\ndata = response.json()"
          }
        ]
      }
    }
  },
  "webhooks": {
    "ask.completed": {
      "post": {
        "operationId": "webhook_ask_completed",
        "summary": "Ask completed",
        "description": "Everything you asked a client for is in (documents today).",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "ask.completed"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "ask_id": {
                        "type": "string",
                        "description": "The Ask, like `req_…` for a document request."
                      },
                      "kind": {
                        "type": "string",
                        "description": "What was asked for. `documents` today; more kinds will come."
                      },
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "ask_id",
                      "kind",
                      "conversation_id",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "ask.completed",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "ask_id": "req_8k2m4q7rx9tbw3hd",
                  "kind": "documents",
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "summary": "Everything you asked for is in",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "client.replied": {
      "post": {
        "operationId": "webhook_client_replied",
        "summary": "Client replied",
        "description": "Someone wrote back on a conversation.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "client.replied"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "message_id": {
                        "type": "string",
                        "description": "Their message, like `msg_…`."
                      },
                      "mailbox_id": {
                        "type": "string",
                        "description": "The inbox it arrived in, like `mbx_…`."
                      },
                      "secure": {
                        "type": "boolean",
                        "description": "True when they replied on a secure page, not by email."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "message_id",
                      "mailbox_id",
                      "secure",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "client.replied",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "message_id": "msg_7h2kq9m3x1c8v5bn",
                  "mailbox_id": "mbx_d56zb3gp9g8qj3qt",
                  "secure": false,
                  "summary": "Dana Wu replied",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "conversation.assigned": {
      "post": {
        "operationId": "webhook_conversation_assigned",
        "summary": "Conversation assigned",
        "description": "A conversation was given to someone, or to nobody.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "conversation.assigned"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "assignee": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "agent"
                                ]
                              },
                              "id": {
                                "type": "string",
                                "description": "A `usr_…` or `agt_…` id."
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "type",
                              "id",
                              "name"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Who has it now, or null when nobody does."
                      },
                      "assigned_by": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "user",
                              "agent",
                              "system"
                            ]
                          },
                          "id": {
                            "description": "Null when Rookery itself did it.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "name": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "type",
                          "id",
                          "name"
                        ]
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "assignee",
                      "assigned_by",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "conversation.assigned",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "assignee": {
                    "type": "user",
                    "id": "usr_4k8m2q9wx7hd3rtn",
                    "name": "Jess"
                  },
                  "assigned_by": {
                    "type": "agent",
                    "id": "agt_3n7q2wv9k4hxm8tr",
                    "name": "Support bot"
                  },
                  "summary": "Assigned to Jess",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "turn.changed": {
      "post": {
        "operationId": "webhook_turn_changed",
        "summary": "Turn changed",
        "description": "Whose turn it is changed: yours, theirs, or done.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "turn.changed"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "turn": {
                        "type": "string",
                        "enum": [
                          "ours",
                          "theirs",
                          "done"
                        ],
                        "description": "`ours`: your team's turn. `theirs`: waiting on them. `done`: closed."
                      },
                      "previous": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "ours",
                              "theirs",
                              "done"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "The turn before, or null the first time."
                      },
                      "assignee": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "agent"
                                ]
                              },
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "type",
                              "id",
                              "name"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Who it's assigned to, if anyone."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "turn",
                      "previous",
                      "assignee",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "turn.changed",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "turn": "ours",
                  "previous": "theirs",
                  "assignee": {
                    "type": "user",
                    "id": "usr_4k8m2q9wx7hd3rtn",
                    "name": "Jess"
                  },
                  "summary": "Jess's turn",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "draft.approved": {
      "post": {
        "operationId": "webhook_draft_approved",
        "summary": "Draft approved",
        "description": "A person approved a helper's or an agent's draft.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "draft.approved"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "message_id": {
                        "type": "string",
                        "description": "The approved reply, like `msg_…`. It goes out after the undo window."
                      },
                      "drafted_by": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "anyOf": [
                              {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "agent"
                                ]
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "type",
                          "id"
                        ]
                      },
                      "approved_by": {
                        "type": "object",
                        "properties": {
                          "type": {
                            "type": "string",
                            "enum": [
                              "user",
                              "agent",
                              "system"
                            ]
                          },
                          "id": {
                            "description": "Null when Rookery itself did it.",
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "name": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "type",
                          "id",
                          "name"
                        ]
                      },
                      "edited": {
                        "type": "boolean",
                        "description": "True when the person changed the draft before approving it."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "message_id",
                      "drafted_by",
                      "approved_by",
                      "edited",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "draft.approved",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "message_id": "msg_9q2w7k4hx3mr8dtb",
                  "drafted_by": {
                    "type": "agent",
                    "id": "agt_3n7q2wv9k4hxm8tr"
                  },
                  "approved_by": {
                    "type": "user",
                    "id": "usr_4k8m2q9wx7hd3rtn",
                    "name": "Jess"
                  },
                  "edited": true,
                  "summary": "Jess approved a draft",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "message.sent": {
      "post": {
        "operationId": "webhook_message_sent",
        "summary": "Email sent",
        "description": "An email went out.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "message.sent"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "message_id": {
                        "type": "string",
                        "description": "The email that went out, like `msg_…`."
                      },
                      "mailbox_id": {
                        "type": "string",
                        "description": "The inbox it went from, like `mbx_…`."
                      },
                      "author": {
                        "anyOf": [
                          {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "user",
                                  "agent"
                                ]
                              },
                              "id": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            },
                            "required": [
                              "type",
                              "id"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "Who wrote it, or null for Rookery's own mail."
                      },
                      "secure": {
                        "type": "boolean",
                        "description": "True when it went as a secure link."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "message_id",
                      "mailbox_id",
                      "author",
                      "secure",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "message.sent",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "message_id": "msg_9q2w7k4hx3mr8dtb",
                  "mailbox_id": "mbx_d56zb3gp9g8qj3qt",
                  "author": {
                    "type": "user",
                    "id": "usr_4k8m2q9wx7hd3rtn"
                  },
                  "secure": false,
                  "summary": "Email sent",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "booking.created": {
      "post": {
        "operationId": "webhook_booking_created",
        "summary": "Booking made",
        "description": "Someone booked a time with you.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "booking.created"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "booking_id": {
                        "type": "string"
                      },
                      "booking_type_id": {
                        "type": "string"
                      },
                      "host_user_id": {
                        "type": "string",
                        "description": "The person they booked with, like `usr_…`."
                      },
                      "conversation_id": {
                        "anyOf": [
                          {
                            "type": "string",
                            "description": "The conversation, like `cnv_…`. Read it with the API."
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "The conversation it's part of, if any."
                      },
                      "starts_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "ends_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "booking_id",
                      "booking_type_id",
                      "host_user_id",
                      "conversation_id",
                      "starts_at",
                      "ends_at",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "booking.created",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "booking_id": "bkg_2m8k4q9wx3hd7rtn",
                  "booking_type_id": "bkt_6t2k9q4wm8xh3drn",
                  "host_user_id": "usr_4k8m2q9wx7hd3rtn",
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "starts_at": "2026-10-14T15:00:00.000Z",
                  "ends_at": "2026-10-14T15:30:00.000Z",
                  "summary": "Dana Wu booked Intro call",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "booking.cancelled": {
      "post": {
        "operationId": "webhook_booking_cancelled",
        "summary": "Booking cancelled",
        "description": "A booking was cancelled.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "booking.cancelled"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "booking_id": {
                        "type": "string"
                      },
                      "booking_type_id": {
                        "type": "string"
                      },
                      "host_user_id": {
                        "type": "string",
                        "description": "The person they had booked with, like `usr_…`."
                      },
                      "conversation_id": {
                        "anyOf": [
                          {
                            "type": "string",
                            "description": "The conversation, like `cnv_…`. Read it with the API."
                          },
                          {
                            "type": "null"
                          }
                        ],
                        "description": "The conversation it's part of, if any."
                      },
                      "starts_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "ends_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "booking_id",
                      "booking_type_id",
                      "host_user_id",
                      "conversation_id",
                      "starts_at",
                      "ends_at",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "booking.cancelled",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "booking_id": "bkg_2m8k4q9wx3hd7rtn",
                  "booking_type_id": "bkt_6t2k9q4wm8xh3drn",
                  "host_user_id": "usr_4k8m2q9wx7hd3rtn",
                  "conversation_id": null,
                  "starts_at": "2026-10-14T15:00:00.000Z",
                  "ends_at": "2026-10-14T15:30:00.000Z",
                  "summary": "Dana Wu cancelled Intro call"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "scout.held": {
      "post": {
        "operationId": "webhook_scout_held",
        "summary": "Held by Scout",
        "description": "Scout held a likely scam.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "scout.held"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "conversation_id": {
                        "type": "string",
                        "description": "The conversation, like `cnv_…`. Read it with the API."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "conversation_id",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "scout.held",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "conversation_id": "cnv_zys19vqj63sb1z4v",
                  "summary": "Held by Scout: The sender asks you to pay a new bank account.",
                  "url": "https://app.userookery.com/c/cnv_zys19vqj63sb1z4v"
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    },
    "webhook.test": {
      "post": {
        "operationId": "webhook_webhook_test",
        "summary": "Test event",
        "description": "Sent when you press Send test event.",
        "tags": [
          "Webhook events"
        ],
        "security": [],
        "parameters": [
          {
            "name": "webhook-id",
            "in": "header",
            "required": true,
            "description": "The event's id, the same as `id` in the body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-timestamp",
            "in": "header",
            "required": true,
            "description": "When this try was sent, in seconds since 1970.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "webhook-signature",
            "in": "header",
            "required": true,
            "description": "`v1,` and a base64 HMAC-SHA256 of `webhook-id.webhook-timestamp.body`, keyed with your `whsec_` secret. Two, separated by a space, for 24 hours after a rotation.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The event, like `evt_…`. The same on every try and on a Resend: skip ones you've handled."
                  },
                  "type": {
                    "type": "string",
                    "const": "webhook.test"
                  },
                  "version": {
                    "type": "number",
                    "const": 1,
                    "description": "Changes only when the event changes in a breaking way."
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When it happened."
                  },
                  "workspace": {
                    "type": "string",
                    "description": "Your workspace, like `wsp_…`."
                  },
                  "data": {
                    "type": "object",
                    "properties": {
                      "endpoint_id": {
                        "type": "string",
                        "description": "The webhook it was sent to, like `whk_…`."
                      },
                      "summary": {
                        "type": "string",
                        "maxLength": 200,
                        "description": "One line, in plain words. Never the email's own words."
                      },
                      "url": {
                        "description": "A link to the conversation in Rookery, when there is one.",
                        "type": "string"
                      }
                    },
                    "required": [
                      "endpoint_id",
                      "summary"
                    ]
                  }
                },
                "required": [
                  "id",
                  "type",
                  "version",
                  "created_at",
                  "workspace",
                  "data"
                ]
              },
              "example": {
                "id": "evt_4pj6sy63n8spf4h9",
                "type": "webhook.test",
                "version": 1,
                "created_at": "2026-10-13T09:14:02.118Z",
                "workspace": "wsp_0qadwjbmg1dw6wws",
                "data": {
                  "endpoint_id": "whk_5d9w2k7hq3mx8rtn",
                  "summary": "A test event from Rookery. If you can read this, it works."
                }
              }
            }
          }
        },
        "responses": {
          "410": {
            "description": "Stop sending: Rookery turns the webhook off and emails its owner."
          },
          "2XX": {
            "description": "Delivered. Answer within 10 seconds; do slow work afterwards."
          },
          "default": {
            "description": "Anything else is tried again after about 30 seconds, 2 minutes, 10 minutes, 30 minutes, 1 hour, 3 hours, 6 hours and 12 hours, then given up."
          }
        },
        "x-rookery-event-version": 1
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key from Settings → Integrations → API keys, like `rk_…`. What it may do depends on its scopes: `read` (conversations, messages, notes, documents and the team), `write` (notes, tags, status and assignment), `draft` (drafts wait for a person to approve them), `send` (replies go out after a 10-minute undo window)."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "What went wrong, in a sentence."
          }
        },
        "required": [
          "error"
        ],
        "example": {
          "error": "This key doesn't have the \"write\" scope."
        }
      }
    }
  }
}
