Files
warmbly/docs/public/openapi.json

30837 lines
826 KiB
JSON

{
"openapi": "3.1.0",
"info": {
"title": "Warmbly API",
"version": "1.0.0",
"description": "The Warmbly API lets you drive mailboxes, campaigns, contacts, the unibox, CRM, and more programmatically. Authenticate with an API key as a Bearer token. All paths are relative to the versioned base URL.",
"contact": {
"name": "Warmbly",
"url": "https://docs.warmbly.com"
},
"license": {
"name": "Proprietary",
"url": "https://warmbly.com"
}
},
"servers": [
{
"url": "https://api.warmbly.com/v1",
"description": "Production (v1)"
}
],
"security": [
{
"bearerAuth": []
}
],
"tags": [
{
"name": "auth",
"description": "Authentication: login, registration, password reset, 2FA, and sessions."
},
{
"name": "mailboxes",
"description": "Connected sending mailboxes and their warmup lifecycle."
},
{
"name": "campaigns",
"description": "Cold outreach campaigns, steps, and A/B variants."
},
{
"name": "contacts",
"description": "Contacts and their tags."
},
{
"name": "unibox",
"description": "Unified inbox: threads, replies, and labels."
},
{
"name": "crm",
"description": "Deals, tasks, notes, and pipelines."
},
{
"name": "api-keys",
"description": "API key management and usage logs."
},
{
"name": "webhooks",
"description": "Outbound webhook endpoints and deliveries."
},
{
"name": "analytics",
"description": "Campaign and deliverability analytics."
},
{
"name": "integrations",
"description": "Third-party connections and automations."
},
{
"name": "account-org",
"description": "Account, organization, and plan reference data."
},
{
"name": "deliverability-ops",
"description": "Deliverability event ingest, suppression, and seed placement."
},
{
"name": "ai",
"description": "The AI tool registry over REST, for function-calling agents that do not speak MCP."
}
],
"paths": {
"/auth/login": {
"post": {
"operationId": "auth_login_start",
"summary": "Start login (request email code)",
"description": "Step 1 of email login. Verifies the email/password and Turnstile token, then emails a one-time confirmation code. Returns an opaque session handle to pass to /auth/login/confirm.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthCredentials"
}
}
}
},
"responses": {
"200": {
"description": "Confirmation code sent; returns the session handle.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthSession"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/login/confirm": {
"post": {
"operationId": "auth_login_confirm",
"summary": "Confirm login (exchange code for tokens)",
"description": "Step 2 of email login. Exchanges the session handle plus the emailed code for a token pair. If 2FA is enabled, returns a 2FA challenge (pending_token) instead of a session.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfirmRequest"
}
}
}
},
"responses": {
"200": {
"description": "Login result: either a full token pair, or a 2FA challenge.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginResult"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Wrong or expired code, or invalid session.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited / too many attempts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/register": {
"post": {
"operationId": "auth_register_start",
"summary": "Start registration (request email code)",
"description": "Step 1 of registration. Validates email/password and Turnstile, then emails a confirmation code. Returns an opaque session handle for /auth/register/confirm.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthCredentials"
}
}
}
},
"responses": {
"200": {
"description": "Confirmation code sent; returns the session handle.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuthSession"
}
}
}
},
"400": {
"description": "Invalid request body or weak password.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Email already in use or not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/register/confirm": {
"post": {
"operationId": "auth_register_confirm",
"summary": "Confirm registration",
"description": "Step 2 of registration. Exchanges the session handle plus the emailed code to finalize the account. Returns 204 on success.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConfirmRequest"
}
}
}
},
"responses": {
"204": {
"description": "Account confirmed."
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Wrong or expired code, or invalid session.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/refresh": {
"post": {
"operationId": "auth_refresh",
"summary": "Refresh the token pair",
"description": "Exchanges a valid refresh token for a new token pair (rotating refresh).",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RefreshRequest"
}
}
}
},
"responses": {
"200": {
"description": "A fresh token pair.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenPair"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Refresh token invalid, expired, or revoked.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/reset-password": {
"post": {
"operationId": "auth_reset_password_start",
"summary": "Start password reset",
"description": "Sends a password-reset code to the email if an account exists. Always returns 200 to avoid account enumeration.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResetPasswordStartRequest"
}
}
}
},
"responses": {
"200": {
"description": "Reset email sent if the account exists."
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/reset-password/confirm": {
"post": {
"operationId": "auth_reset_password_confirm",
"summary": "Confirm password reset",
"description": "Exchanges the reset session handle plus a new password to set a new password.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ResetPasswordConfirmRequest"
}
}
}
},
"responses": {
"200": {
"description": "Password updated."
},
"400": {
"description": "Invalid request body or weak password.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Invalid or expired reset session.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Turnstile / captcha rejected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/2fa/verify": {
"post": {
"operationId": "auth_2fa_verify_login",
"summary": "Verify 2FA login challenge",
"description": "Exchanges the single-use pending_token from /auth/login/confirm plus a TOTP or recovery code for a real token pair.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFAVerifyRequest"
}
}
}
},
"responses": {
"200": {
"description": "A full token pair.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenPair"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Pending token invalid/expired, or code wrong.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Too many attempts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/passkey/login/begin": {
"post": {
"operationId": "auth_passkey_login_begin",
"summary": "Begin passkey (WebAuthn) login",
"description": "Starts a discoverable/usernameless passkey login. Returns the WebAuthn assertion options plus an opaque session handle to pass to /auth/passkey/login/finish.",
"tags": [
"auth"
],
"security": [],
"responses": {
"200": {
"description": "WebAuthn assertion options and the login session handle.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasskeyLoginChallenge"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/passkey/login/finish": {
"post": {
"operationId": "auth_passkey_login_finish",
"summary": "Finish passkey (WebAuthn) login",
"description": "Submits the WebAuthn assertion together with the login session handle. On success returns a full token pair.",
"tags": [
"auth"
],
"security": [],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasskeyLoginFinishRequest"
}
}
}
},
"responses": {
"200": {
"description": "A full token pair.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenPair"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Assertion rejected or session invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/logout": {
"post": {
"operationId": "auth_logout",
"summary": "Log out the current session",
"description": "Revokes the session bound to the bearer access token. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Session revoked."
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/logout-all": {
"post": {
"operationId": "auth_logout_all",
"summary": "Log out all sessions",
"description": "Revokes every active session for the authenticated user. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "All sessions revoked."
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/me": {
"get": {
"operationId": "auth_get_me",
"summary": "Get the authenticated user",
"description": "Returns the current user profile, including per-user folders, tags, and categories. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The authenticated user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "auth_update_me",
"summary": "Update the authenticated user's profile",
"description": "Updates basic profile fields for the current user. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateProfileRequest"
}
}
}
},
"responses": {
"200": {
"description": "The updated user.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/me/password": {
"post": {
"operationId": "auth_change_password",
"summary": "Change password",
"description": "Changes the signed-in user's password (current + new). Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChangePasswordRequest"
}
}
}
},
"responses": {
"200": {
"description": "Password changed."
},
"400": {
"description": "Invalid request body or weak new password.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Current password wrong or session invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/sessions": {
"get": {
"operationId": "auth_list_sessions",
"summary": "List active sessions",
"description": "Lists the authenticated user's active sessions, with the caller's current session flagged. Requires a user session token (not an API key). This endpoint returns a plain array, not a paginated wrapper.",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Active sessions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionList"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "auth_revoke_other_sessions",
"summary": "Revoke all other sessions",
"description": "Ends every active session except the current one. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Other sessions revoked."
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/sessions/{id}": {
"delete": {
"operationId": "auth_revoke_session",
"summary": "Revoke a specific session",
"description": "Ends one of the user's sessions by id. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Session id to revoke."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Session revoked."
},
"400": {
"description": "Invalid session id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Session not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/2fa/status": {
"get": {
"operationId": "auth_2fa_status",
"summary": "Get 2FA status",
"description": "Reports whether the authenticated user has 2FA enabled. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "2FA status.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFAStatus"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/2fa/enroll/start": {
"post": {
"operationId": "auth_2fa_enroll_start",
"summary": "Begin 2FA enrollment",
"description": "Generates a fresh TOTP secret and otpauth provisioning URI (shown once). Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "The TOTP secret and otpauth URI.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFAEnrollStart"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/2fa/enroll/confirm": {
"post": {
"operationId": "auth_2fa_enroll_confirm",
"summary": "Confirm 2FA enrollment",
"description": "Verifies a TOTP code, enables 2FA, and returns one-time recovery codes (shown once). Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFACodeRequest"
}
}
}
},
"responses": {
"200": {
"description": "Recovery codes.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFARecoveryCodes"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Wrong code or session invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/2fa": {
"delete": {
"operationId": "auth_2fa_disable",
"summary": "Disable 2FA",
"description": "Turns off 2FA for the user. Requires a current TOTP or recovery code in the body. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TwoFACodeRequest"
}
}
}
},
"responses": {
"200": {
"description": "2FA disabled.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OkResponse"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Wrong code or session invalid.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/passkey/credentials": {
"get": {
"operationId": "auth_list_passkey_credentials",
"summary": "List passkey credentials",
"description": "Lists the authenticated user's registered passkeys. Requires a user session token (not an API key). Returns a plain array, not a paginated wrapper.",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Registered passkeys.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasskeyCredentialList"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/auth/passkey/credentials/{id}": {
"patch": {
"operationId": "auth_rename_passkey_credential",
"summary": "Rename a passkey",
"description": "Renames a registered passkey by id. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Passkey credential id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasskeyRenameRequest"
}
}
}
},
"responses": {
"200": {
"description": "The updated passkey.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasskeyCredential"
}
}
}
},
"400": {
"description": "Invalid request body or id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Passkey not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "auth_delete_passkey_credential",
"summary": "Delete a passkey",
"description": "Removes a registered passkey by id. Requires a user session token (not an API key).",
"tags": [
"auth"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Passkey credential id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Passkey deleted."
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid session token.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Not allowed.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Passkey not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails": {
"get": {
"operationId": "mailboxes_list",
"summary": "List mailboxes",
"description": "Returns the organization's connected mailboxes, newest first, with cursor pagination.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": false,
"description": "Free-text search over mailbox address and name.",
"schema": {
"type": "string"
}
},
{
"name": "tag",
"in": "query",
"required": false,
"description": "Tag id to filter by.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination token from a previous pagination.next_cursor.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size. Default 50, max 100.",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100,
"minimum": 1
}
}
],
"responses": {
"200": {
"description": "A page of mailboxes.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxList"
}
}
}
},
"400": {
"description": "Invalid cursor, limit, or tag.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}": {
"get": {
"operationId": "mailboxes_get",
"summary": "Get a mailbox",
"description": "Returns a single mailbox by id.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox (email account) id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The mailbox.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "mailboxes_update",
"summary": "Update a mailbox",
"description": "Updates mailbox settings. All fields are optional; only present fields are applied.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated mailbox.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid request body or id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "mailboxes_delete",
"summary": "Delete a mailbox",
"description": "Disconnects and deletes a mailbox. It is removed from all warmup pools.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"204": {
"description": "Mailbox deleted."
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/track": {
"patch": {
"operationId": "mailboxes_update_tracking_domain",
"summary": "Update the tracking domain",
"description": "Sets or clears the custom open/click tracking domain for a mailbox. Send an empty domain to clear it and fall back to the shared default.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "domain",
"in": "query",
"required": false,
"description": "The custom tracking subdomain (for example t.acme.com). Empty clears it.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "The resolved tracking-domain state.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxTrackingDomain"
}
}
}
},
"400": {
"description": "Invalid id or domain.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/start": {
"post": {
"operationId": "mailboxes_warmup_start",
"summary": "Start warmup",
"description": "Enables warmup for a mailbox. When resuming from a paused state it preserves ramp progress.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The updated mailbox.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/pause": {
"post": {
"operationId": "mailboxes_warmup_pause",
"summary": "Pause warmup",
"description": "Pauses warmup without losing ramp progress. A later start continues from the same daily volume.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The updated mailbox. A paused mailbox has a non-null warmup_paused_at.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/resume": {
"post": {
"operationId": "mailboxes_warmup_resume",
"summary": "Resume warmup",
"description": "Resumes a paused warmup, shifting the ramp anchor forward so progress continues where it left off.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The updated mailbox, with warmup_paused_at cleared.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/stop": {
"post": {
"operationId": "mailboxes_warmup_stop",
"summary": "Stop warmup",
"description": "Disables warmup entirely and clears ramp progress. A later start begins a fresh ramp.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The updated mailbox, with warmup disabled.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Mailbox"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/auth-check": {
"get": {
"operationId": "mailboxes_auth_check",
"summary": "Check domain authentication",
"description": "Validates SPF, DKIM, and DMARC for the mailbox's sending domain on demand.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id. The domain is derived from the mailbox address.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The authentication-check result.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxAuthCheck"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/sync": {
"get": {
"operationId": "mailboxes_sync_state",
"summary": "Get sync state",
"description": "Where the mailbox's initial import stands, whether fair use is holding new mail, and the budget the mailbox syncs under. `state` is null until the worker has reported once.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The mailbox's sync state and policy.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxSync"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/verify": {
"post": {
"operationId": "mailboxes_verify_address",
"summary": "Verify an email address",
"description": "Verifies a single email address on demand (syntax, MX, SMTP RCPT probe, catch-all detection). The address may be supplied in the JSON body or as the email query param; the body takes precedence.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "email",
"in": "query",
"required": false,
"description": "The address to verify. Used when not supplied in the body.",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxVerifyRequest"
}
}
}
},
"responses": {
"200": {
"description": "The verification result.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxVerifyResult"
}
}
}
},
"400": {
"description": "Missing or empty address.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/ban-status": {
"get": {
"operationId": "mailboxes_warmup_ban_status",
"summary": "Get warmup ban status",
"description": "Returns whether a mailbox is blocked from the shared warmup pool, why, and whether the owner can appeal.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The warmup ban status.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxWarmupBanStatus"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/warmup/appeal": {
"post": {
"operationId": "mailboxes_warmup_appeal",
"summary": "Submit a warmup appeal",
"description": "Lets the mailbox owner appeal a warmup ban with a reason.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxWarmupAppealRequest"
}
}
}
},
"responses": {
"200": {
"description": "The created appeal id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxWarmupAppealResult"
}
}
}
},
"400": {
"description": "Invalid id or request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/emails/{id}/send": {
"post": {
"operationId": "mailboxes_send",
"summary": "Send from a mailbox",
"description": "Sends a one-off email from a specific mailbox, scheduled and dispatched through the mailbox's assigned worker. Requires an active organization.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
},
{
"name": "id",
"in": "path",
"required": true,
"description": "The sending mailbox id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxSendRequest"
}
}
}
},
"responses": {
"200": {
"description": "The queued send task.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MailboxSendResult"
}
}
}
},
"400": {
"description": "Invalid id, request body, or no active organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope, permission, or mailbox not allowed for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Mailbox not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns": {
"get": {
"operationId": "campaigns_list",
"summary": "List campaigns",
"description": "Search and page through the organization's campaigns. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": false,
"description": "Free-text filter on campaign name.",
"schema": {
"type": "string"
}
},
{
"name": "folder",
"in": "query",
"required": false,
"description": "Restrict to a single folder id.",
"schema": {
"type": "string"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from the previous page.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size (default 50, max 100).",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100,
"minimum": 1
}
}
],
"responses": {
"200": {
"description": "A page of campaigns.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignList"
}
}
}
},
"400": {
"description": "Invalid cursor or limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "campaigns_create",
"summary": "Create a campaign",
"description": "Create a campaign. Only name is required. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignCreate"
}
}
}
},
"responses": {
"201": {
"description": "The created campaign.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}": {
"get": {
"operationId": "campaigns_get",
"summary": "Get a campaign",
"description": "Fetch a single campaign by id. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The campaign.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "campaigns_update",
"summary": "Update a campaign",
"description": "Patch any subset of campaign fields. Omitted fields are unchanged. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated campaign.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Campaign"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "campaigns_delete",
"summary": "Delete a campaign",
"description": "Permanently delete a campaign. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deleted."
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/advanced": {
"get": {
"operationId": "campaigns_get_advanced",
"summary": "Get advanced settings",
"description": "Return the campaign's advanced outreach overrides. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The advanced settings.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAdvancedSettings"
}
}
}
},
"400": {
"description": "Invalid id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "campaigns_update_advanced",
"summary": "Update advanced settings",
"description": "Replace the campaign's advanced overrides. Scope WRITE_CAMPAIGNS, org permission manage_settings.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAdvancedUpdate"
}
}
}
},
"responses": {
"204": {
"description": "Updated."
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/ab-variants": {
"get": {
"operationId": "campaigns_list_ab_variants",
"summary": "List A/B variants",
"description": "List the campaign's A/B variants. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The variants.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignABVariantList"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "campaigns_create_ab_variant",
"summary": "Create an A/B variant",
"description": "Add a variant to the campaign (or one step via step_id). Scope WRITE_CAMPAIGNS, org permission manage_settings.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignABVariantCreate"
}
}
}
},
"responses": {
"201": {
"description": "The created variant.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignABVariant"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/ab-variants/{variantId}": {
"patch": {
"operationId": "campaigns_update_ab_variant",
"summary": "Update an A/B variant",
"description": "Patch a variant. Omitted fields are unchanged. Scope WRITE_CAMPAIGNS, org permission manage_settings.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "variantId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignABVariantUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated variant.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignABVariant"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "campaigns_delete_ab_variant",
"summary": "Delete an A/B variant",
"description": "Remove a variant. Scope WRITE_CAMPAIGNS, org permission manage_settings.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "variantId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deleted."
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/ab-analysis": {
"get": {
"operationId": "campaigns_get_ab_analysis",
"summary": "Get A/B analysis",
"description": "Return per-variant engagement stats and the computed winner. Scope READ_ANALYTICS, org permission view_analytics.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The A/B analysis.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ABWinnerAnalysis"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/attachments": {
"get": {
"operationId": "campaigns_list_attachments",
"summary": "List attachments",
"description": "List the campaign's attachments, each with a short-lived presigned download url. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The attachments.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAttachmentList"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "campaigns_upload_attachment",
"summary": "Upload an attachment",
"description": "Upload a file (max 15 MB) to attach to the campaign or one step. Multipart form data. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"file"
],
"properties": {
"file": {
"type": "string",
"format": "binary",
"description": "The file to upload (max 15 MB). Executable and script types are rejected."
},
"step_id": {
"type": "string",
"format": "uuid",
"description": "Scope the attachment to one sequence step of this campaign, which is then the only step that sends it. Omit to attach the file to every step. A step of another campaign is 404."
}
}
}
}
}
},
"responses": {
"201": {
"description": "The created attachment.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAttachment"
}
}
}
},
"400": {
"description": "Validation error or rejected file type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/attachments/{attachmentId}": {
"delete": {
"operationId": "campaigns_delete_attachment",
"summary": "Delete an attachment",
"description": "Delete a campaign attachment and its stored object. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "attachmentId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deleted."
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/preflight": {
"post": {
"operationId": "campaigns_run_preflight",
"summary": "Run preflight",
"description": "Run the campaign's preflight validation checks and return a scored report. No mail is sent. Scope SEND_CAMPAIGNS, org permission send_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "The preflight report.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PreflightReport"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/test-email": {
"post": {
"operationId": "campaigns_send_test_email",
"summary": "Send a test email",
"description": "Send a one-off preview of a sequence step to a recipient through a chosen mailbox. Scope SEND_CAMPAIGNS, org permission send_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignTestEmailRequest"
}
}
}
},
"responses": {
"200": {
"description": "Test email sent.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignTestEmailResult"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/start": {
"post": {
"operationId": "campaigns_start",
"summary": "Start a campaign",
"description": "Activate the campaign so it begins sending real mail. Scope SEND_CAMPAIGNS, org permission send_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Started.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignStartResult"
}
}
}
},
"400": {
"description": "Campaign not in a startable state.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/stop": {
"post": {
"operationId": "campaigns_stop",
"summary": "Stop a campaign",
"description": "Pause an active campaign. Scope SEND_CAMPAIGNS, org permission send_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Stopped.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignStopResult"
}
}
}
},
"400": {
"description": "Campaign not in a stoppable state.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/logs": {
"get": {
"operationId": "campaigns_list_logs",
"summary": "Get campaign logs",
"description": "Page through the campaign's activity log. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from the previous page.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100 (default 50).",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100,
"minimum": 1
}
}
],
"responses": {
"200": {
"description": "A page of log entries.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignLogList"
}
}
}
},
"400": {
"description": "Invalid cursor or limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/senders": {
"get": {
"operationId": "campaigns_list_senders",
"summary": "List campaign senders",
"description": "Return the campaign's explicit sender pool. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The sender pool.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSenderList"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"operationId": "campaigns_replace_senders",
"summary": "Replace senders",
"description": "Atomically replace the campaign's explicit sender pool. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSendersReplace"
}
}
}
},
"responses": {
"200": {
"description": "The resulting sender pool.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignSenderList"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/tracking-domain/verify": {
"post": {
"operationId": "campaigns_verify_tracking_domain",
"summary": "Verify campaign tracking domain",
"description": "Resolve the campaign-scoped tracking domain's CNAME and flip tracking_domain_verified on success. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "The tracking-domain status.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TrackingDomainStatus"
}
}
}
},
"400": {
"description": "Verification failed or no domain configured.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/steps": {
"get": {
"operationId": "campaigns_list_steps",
"summary": "List steps",
"description": "Return the campaign's sequence steps in order. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The sequence steps (bare array, no envelope).",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignStep"
}
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "campaigns_create_step",
"summary": "Create a step",
"description": "Append a new empty sequence step created with defaults, then edited with PATCH. No request body. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"201": {
"description": "The created step.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignStep"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaigns/{id}/steps/{sid}": {
"patch": {
"operationId": "campaigns_update_step",
"summary": "Update a step",
"description": "Patch a sequence step: copy, spacing, node kind, branching tree, or action config. Omitted fields are unchanged. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "sid",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignStepUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated step.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignStep"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "campaigns_delete_step",
"summary": "Delete a step",
"description": "Delete a sequence step. Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "sid",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Deleted (empty body)."
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/campaign-template-preview": {
"post": {
"operationId": "campaigns_template_preview",
"summary": "Preview a template",
"description": "Render subject and body templates against a sample (or supplied) contact and report parse errors plus unresolved tokens. No side effects. Scope READ_CAMPAIGNS, org permission view_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplatePreviewRequest"
}
}
}
},
"responses": {
"200": {
"description": "The rendered preview.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplatePreview"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/generation/write": {
"post": {
"operationId": "campaigns_generate_writing",
"summary": "Generate copy with the writing assistant",
"description": "Generate outreach copy with the AI writing assistant. Gated to paid and free-trial orgs; consumes one AI credit (refunded on provider failure). Scope WRITE_CAMPAIGNS, org permission manage_campaigns.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerationWriteRequest"
}
}
}
},
"responses": {
"200": {
"description": "The generated copy.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerationWriteResult"
}
}
}
},
"400": {
"description": "Validation error.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"402": {
"description": "Out of AI credits (code insufficient_credits).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/search": {
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_search",
"summary": "Search contacts",
"description": "Faceted, org-scoped contact search. Filters live in the body; pagination is via query params. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from the previous page's pagination.next_cursor. It carries the exact position of the next page under the ordering it was issued for, so rows that share a sort value are never skipped or repeated. A malformed cursor, or one replayed with a different sort_by or reverse than it was issued under, is a 400.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size (numeric string). Default 50, max 100.",
"schema": {
"type": "string"
}
},
{
"name": "category",
"in": "query",
"required": false,
"description": "Convenience filter for a single category ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"required": false,
"description": "All filters optional; an empty body matches every contact in the organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactSearchRequest"
}
}
}
},
"responses": {
"200": {
"description": "Matching contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactList"
}
}
}
},
"400": {
"description": "Invalid body, cursor, or limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts": {
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_create",
"summary": "Create contacts",
"description": "Creates one or more contacts. The body is a JSON array, so a single create is an array of length one. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/components/schemas/ContactCreate"
}
}
}
}
},
"responses": {
"200": {
"description": "The created contacts as a bare array.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Contact"
}
}
}
}
},
"400": {
"description": "Empty array or too many contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"tags": [
"contacts"
],
"operationId": "contacts_bulk_update",
"summary": "Bulk update contacts",
"description": "Applies one set of edits across a selection of contacts (up to 1000 by ID, or everything a filter matches, up to 50000): add/remove campaigns and categories, custom-field operations, and subscription. Scope `BULK_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactBulkUpdateRequest"
}
}
}
},
"responses": {
"200": {
"description": "The updated contacts as a bare array.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Contact"
}
}
}
}
},
"400": {
"description": "A selection that names nothing, an explicit list over 1000 or an exclusion list over 50000 (`too_many_contacts`), a select-all with no filters, a filter matching no contacts, or a filter matching more than 50000 (`selection_too_large`).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks BULK_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"tags": [
"contacts"
],
"operationId": "contacts_bulk_delete",
"summary": "Bulk delete contacts",
"description": "Deletes a selection of contacts: up to 1000 by ID, or everything a filter matches (up to 50000). Scope `BULK_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"description": "A JSON array of contact ID strings (1 to 1000), or a ContactSelection object naming a filter.",
"content": {
"application/json": {
"schema": {
"oneOf": [
{
"type": "array",
"minItems": 1,
"maxItems": 1000,
"items": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/schemas/ContactSelection"
}
]
}
}
}
},
"responses": {
"204": {
"description": "Contacts deleted."
},
"400": {
"description": "A selection that names nothing, an explicit list over 1000 or an exclusion list over 50000 (`too_many_contacts`), a select-all with no filters, a filter matching no contacts, or a filter matching more than 50000 (`selection_too_large`).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks BULK_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/export": {
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_export",
"summary": "Export contacts",
"description": "Exports contacts to CSV, XLSX, or JSON. The response is the file itself, not JSON. Capped at 50,000 rows. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactExportRequest"
}
}
}
},
"responses": {
"200": {
"description": "The export file as an attachment.",
"headers": {
"Content-Disposition": {
"description": "attachment; filename=\"...\".",
"schema": {
"type": "string"
}
},
"X-Total-Rows": {
"description": "Number of rows written.",
"schema": {
"type": "integer"
}
}
},
"content": {
"text/csv": {
"schema": {
"type": "string",
"format": "binary"
}
},
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
"schema": {
"type": "string",
"format": "binary"
}
},
"application/json": {
"schema": {
"type": "string",
"format": "binary"
}
}
}
},
"400": {
"description": "Invalid format, scope, or filters.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/import/preview": {
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_import_preview",
"summary": "Preview an import",
"description": "Uploads a CSV or XLSX file and returns detected columns plus a sample so the client can build a column mapping. Uploads capped at 50 MB. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"file"
],
"properties": {
"file": {
"type": "string",
"format": "binary",
"description": "The CSV/XLSX upload."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Detected columns, sample rows, and a suggested mapping.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactImportPreview"
}
}
}
},
"400": {
"description": "Missing file, unsupported format, or over the size cap.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/import/commit": {
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_import_commit",
"summary": "Commit an import",
"description": "Re-uploads the file with a mapping and dedup options, applies it, and returns per-row results. Imports capped at 50,000 rows. Scope `BULK_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": [
"file",
"options"
],
"properties": {
"file": {
"type": "string",
"format": "binary",
"description": "The CSV/XLSX upload (max 50 MB)."
},
"options": {
"type": "string",
"description": "JSON-encoded ContactImportCommitOptions as a string."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Per-row import results.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactImportResult"
}
}
}
},
"400": {
"description": "Missing file/options, invalid mapping or dedup, or over a cap.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks BULK_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/lookup": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_lookup",
"summary": "Look up a contact by email",
"description": "Resolves a sender address to a contact. Returns 200 with {\"contact\": null} when nothing matches. A display-name wrapped address (`Name <addr@example.com>`) is accepted and unwrapped. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "email",
"in": "query",
"required": true,
"description": "The email address to resolve.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "The resolved contact, or null.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactLookupResult"
}
}
}
},
"400": {
"description": "Missing or malformed email.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_get",
"summary": "Get a contact",
"description": "Returns the hydrated contact 360 payload: the contact plus an engagement summary and, when present, suppression state. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The hydrated contact.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactDetail"
}
}
}
},
"400": {
"description": "Invalid contact ID.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"tags": [
"contacts"
],
"operationId": "contacts_update",
"summary": "Update a contact",
"description": "Partially updates a single contact; only the fields present change. Category lists can be set wholesale or adjusted with diff-style add/remove. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated contact.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Contact"
}
}
}
},
"400": {
"description": "Invalid contact ID or body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"tags": [
"contacts"
],
"operationId": "contacts_delete",
"summary": "Delete a contact",
"description": "Deletes a single contact. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Contact deleted."
},
"400": {
"description": "Invalid contact ID.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/emails": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_emails_list",
"summary": "List emails sent to a contact",
"description": "One row per email sent (or attempted) to the contact, newest first. Keyset paginated on (created_at, task_id); pass both before_at and before_id together. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200 (default 50).",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
},
{
"name": "before_at",
"in": "query",
"required": false,
"description": "created_at of the last row from the previous page (RFC 3339 nano).",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "before_id",
"in": "query",
"required": false,
"description": "task_id of the last row from the previous page.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Sent emails.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactSentEmailList"
}
}
}
},
"400": {
"description": "Invalid contact ID or limit.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/timeline": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_timeline_list",
"summary": "List a contact's timeline",
"description": "Merged activity feed: sends, opens, clicks, replies, bounces, deliverability/suppression events, notes, meeting bookings, lifecycle events, and website page views. Requires a selected organization. Paginate with the opaque `cursor` from `pagination.next_cursor`; the cursor carries the exact position of the last event (time, source, row), so events that share a timestamp are never skipped or repeated. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200 (default 50).",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from `pagination.next_cursor`. A malformed cursor is a 400.",
"schema": {
"type": "string"
}
},
{
"name": "before",
"in": "query",
"required": false,
"deprecated": true,
"description": "Deprecated: use `cursor`. Returns the events strictly older than this timestamp (RFC 3339 nano), which can skip events that share an instant with the page boundary. Ignored when `cursor` is set.",
"schema": {
"type": "string",
"format": "date-time"
}
}
],
"responses": {
"200": {
"description": "A page of timeline events with the pagination envelope.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactTimelineResult"
}
}
}
},
"400": {
"description": "Invalid contact ID, limit, cursor or before timestamp, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/activities": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_activities_list",
"summary": "List a contact's activities",
"description": "Structured CRM activity log for a contact. Requires a selected organization. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100 (default 50).",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque cursor from the previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "CRM activity log.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactActivityList"
}
}
}
},
"400": {
"description": "Invalid contact ID, cursor, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/notes": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_notes_list",
"summary": "List a contact's notes",
"description": "CRM notes attached to a contact, newest first. Requires a selected organization. Scope `READ_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100 (default 50).",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque cursor from the previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Contact notes.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactNoteList"
}
}
}
},
"400": {
"description": "Invalid contact ID, cursor, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"tags": [
"contacts"
],
"operationId": "contacts_notes_create",
"summary": "Create a contact note",
"description": "Adds a note to a contact. Requires a selected organization. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactNoteCreate"
}
}
}
},
"responses": {
"201": {
"description": "The created note.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactNote"
}
}
}
},
"400": {
"description": "Invalid contact ID, missing/too-long content, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/notes/{noteId}": {
"patch": {
"tags": [
"contacts"
],
"operationId": "contacts_notes_update",
"summary": "Update a contact note",
"description": "Edits a note's content. Requires a selected organization. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "noteId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactNoteUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated note.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ContactNote"
}
}
}
},
"400": {
"description": "Invalid IDs, body, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact or note not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"tags": [
"contacts"
],
"operationId": "contacts_notes_delete",
"summary": "Delete a contact note",
"description": "Deletes a note. Requires a selected organization. Scope `WRITE_CONTACTS`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "noteId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Note deleted."
},
"400": {
"description": "Invalid IDs or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact or note not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/contacts/{id}/deals": {
"get": {
"tags": [
"contacts"
],
"operationId": "contacts_deals_list",
"summary": "List a contact's deals",
"description": "CRM deals associated with a contact, returned as a bare JSON array. Scope `READ_CRM`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The contact's deals.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Deal"
}
}
}
}
},
"400": {
"description": "Invalid contact ID.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CRM or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Contact not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox": {
"get": {
"operationId": "unibox_list",
"summary": "List incoming mail",
"description": "Org-wide inbox list, collapsed to one row per thread (newest message), with filtering and cursor pagination. Excludes snoozed threads unless `snoozed=true`, and the `spam` and `trash` folders unless `folder` selects one of them.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from a previous response.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, clamped to the server min/max.",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
},
{
"name": "from",
"in": "query",
"required": false,
"description": "Filter by sender address (substring).",
"schema": {
"type": "string"
}
},
{
"name": "subject",
"in": "query",
"required": false,
"description": "Filter by subject (substring).",
"schema": {
"type": "string"
}
},
{
"name": "folder",
"in": "query",
"required": false,
"description": "Canonical folder scope. Omit for every folder except `spam` and `trash`.",
"schema": {
"type": "string",
"enum": [
"inbox",
"sent",
"drafts",
"archive",
"spam",
"trash"
]
}
},
{
"name": "unseen",
"in": "query",
"required": false,
"description": "`true` returns only threads with unread messages.",
"schema": {
"type": "boolean"
}
},
{
"name": "awaiting_reply",
"in": "query",
"required": false,
"description": "`true` returns only threads whose latest message was sent by you.",
"schema": {
"type": "boolean"
}
},
{
"name": "snoozed",
"in": "query",
"required": false,
"description": "`true` returns only snoozed threads. Omit to exclude snoozed threads.",
"schema": {
"type": "string"
}
},
{
"name": "since",
"in": "query",
"required": false,
"description": "Lower bound on date, `YYYY-MM-DD`.",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "until",
"in": "query",
"required": false,
"description": "Upper bound on date, `YYYY-MM-DD`.",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "email_id",
"in": "query",
"required": false,
"description": "Restrict to a single mailbox by UUID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "email_ids",
"in": "query",
"required": false,
"description": "Comma-separated mailbox UUIDs. A thread matches if it landed in any of them.",
"schema": {
"type": "string"
}
},
{
"name": "category_ids",
"in": "query",
"required": false,
"description": "Comma-separated conversation-label UUIDs. A thread matches if it carries any of them.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Inbox list page.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxThreadList"
}
}
}
},
"400": {
"description": "Invalid cursor, limit, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/count": {
"get": {
"operationId": "unibox_count",
"summary": "Get unread count",
"description": "Org-wide unread message count, optionally scoped to one mailbox.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "email_id",
"in": "query",
"required": false,
"description": "Optional mailbox UUID to count unread for a single mailbox.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Unread count.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxCount"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/overview": {
"get": {
"operationId": "unibox_overview",
"summary": "Get inbox overview",
"description": "Rolls up scope-rail and metric-strip counts (unread, today, week, snoozed, awaiting-reply, pending-scheduled) plus per-mailbox, per-tag, and per-conversation-label breakdowns.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Inbox overview rollup.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxOverview"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/thread": {
"get": {
"operationId": "unibox_get_thread",
"summary": "Get a thread",
"description": "Every message in a single conversation, with cursor pagination. With no `email_id` the thread is read across every mailbox in the organization.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "thread_id",
"in": "query",
"required": true,
"description": "The thread to read. Also accepted as `id`.",
"schema": {
"type": "string"
}
},
{
"name": "email_id",
"in": "query",
"required": false,
"description": "Optional mailbox UUID to scope the thread to one mailbox. Also accepted as `email`.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size. Out-of-range values return 400.",
"schema": {
"type": "integer",
"default": 50,
"maximum": 100
}
}
],
"responses": {
"200": {
"description": "Thread messages page.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxMessageList"
}
}
}
},
"400": {
"description": "Missing `thread_id`, invalid cursor/limit, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/thread/labels": {
"get": {
"operationId": "unibox_get_thread_labels",
"summary": "Get thread labels",
"description": "Conversation labels (the workspace's categories) attached to a thread.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "thread_id",
"in": "query",
"required": true,
"description": "The thread to read labels for. Also accepted as `id`.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Label set wrapped in a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxLabelList"
}
}
}
},
"400": {
"description": "Missing `thread_id` or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"operationId": "unibox_set_thread_labels",
"summary": "Set thread labels",
"description": "Replaces the full conversation-label set on a thread. `category_ids` is the desired set, so the call is idempotent and retries are naturally safe.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxSetThreadLabelsRequest"
}
}
}
},
"responses": {
"200": {
"description": "Resulting label set wrapped in a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxLabelList"
}
}
}
},
"400": {
"description": "Missing `thread_id` or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/seen": {
"patch": {
"operationId": "unibox_mark_seen",
"summary": "Mark messages seen",
"description": "Marks a batch of messages as read or unread, org-wide. Up to 500 ids per call.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxMarkSeenRequest"
}
}
}
},
"responses": {
"200": {
"description": "Echoes the request back.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxMarkSeenRequest"
}
}
}
},
"400": {
"description": "Invalid body, more than 500 ids, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/folder": {
"patch": {
"operationId": "unibox_move_folder",
"summary": "Move messages between folders",
"description": "Re-files a batch of messages into Inbox, Archive or Trash, org-wide. Up to 500 ids per call.\n\nThis is a move in Warmbly only. The copy at the mail provider stays where it is, and a later sync will not undo the move: Warmbly tracks the provider's own placement separately and follows it only when the provider itself moves the message. `sent`, `drafts` and `spam` are placements the provider reaches, so they are rejected here with a `400`.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxMoveFolderRequest"
}
}
}
},
"responses": {
"200": {
"description": "Echoes the request back.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxMoveFolderRequest"
}
}
}
},
"400": {
"description": "Invalid body, more than 500 ids, a folder outside inbox/archive/trash, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/reply": {
"post": {
"operationId": "unibox_reply",
"summary": "Reply from the inbox",
"description": "Sends or schedules a reply from one of your mailboxes, routed through the per-mailbox scheduler according to `send_mode`. Requires an active organization.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxReplyRequest"
}
}
}
},
"responses": {
"200": {
"description": "Reply queued or scheduled.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxReplyResult"
}
}
}
},
"400": {
"description": "Invalid body, invalid mailbox UUID, missing future `scheduled_at`, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/snoozes": {
"get": {
"operationId": "unibox_list_snoozes",
"summary": "List active snoozes",
"description": "Your active thread snoozes.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Active snoozes wrapped in a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxSnoozeList"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/snooze": {
"post": {
"operationId": "unibox_snooze",
"summary": "Snooze a thread",
"description": "Hides a thread from your inbox until `snoozed_until` passes. Upsert semantics: a second call on the same thread updates the time in place.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxSnoozeRequest"
}
}
}
},
"responses": {
"200": {
"description": "The created or updated snooze.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxSnooze"
}
}
}
},
"400": {
"description": "Invalid body or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "unibox_unsnooze",
"summary": "Unsnooze a thread",
"description": "Un-snoozes a thread immediately. Idempotent: deleting a snooze that does not exist still succeeds with 204.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "thread_id",
"in": "query",
"required": true,
"description": "The thread to un-snooze.",
"schema": {
"type": "string"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Snooze removed (or already absent). Empty body."
},
"400": {
"description": "Missing `thread_id` or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/scheduled": {
"get": {
"operationId": "unibox_list_scheduled",
"summary": "List scheduled sends",
"description": "Outbound emails you have queued but not yet sent. Pass `thread_id` to scope to a single conversation; the response shape is identical either way.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "thread_id",
"in": "query",
"required": false,
"description": "Restrict to scheduled sends queued into one thread.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Queued message previews wrapped in a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxScheduledList"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/scheduled/{task_id}": {
"delete": {
"operationId": "unibox_cancel_scheduled",
"summary": "Cancel a scheduled send",
"description": "Cancels a pending scheduled send before it fires. The queued task is marked cancelled and short-circuits to a no-op when its run time arrives.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "task_id",
"in": "path",
"required": true,
"description": "UUID of the scheduled task to cancel.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Scheduled send cancelled. Empty body."
},
"400": {
"description": "Invalid task id or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Scheduled send not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/unibox/{id}": {
"get": {
"operationId": "unibox_get",
"summary": "Get a message by id",
"description": "A single message by its UUID, including the full envelope and body.",
"tags": [
"unibox"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "UUID of the message.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The message.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UniboxEmail"
}
}
}
},
"400": {
"description": "Invalid message id or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing scope/permission, or organization lacks unified-inbox access.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Message not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/pipelines": {
"get": {
"operationId": "crm_list_pipelines",
"summary": "List pipelines",
"description": "Return every pipeline in the organization, each with its ordered stages. Returns a bare array, not a list envelope.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Array of pipelines (each with its stages).",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pipeline"
}
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "crm_create_pipeline",
"summary": "Create pipeline",
"description": "Create a pipeline, optionally seeding it with an ordered set of stages.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreatePipeline"
}
}
}
},
"responses": {
"201": {
"description": "Created pipeline (including its stages).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pipeline"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/pipelines/{id}": {
"get": {
"operationId": "crm_get_pipeline",
"summary": "Get pipeline",
"description": "Fetch a single pipeline with its stages.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The pipeline.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pipeline"
}
}
}
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "crm_update_pipeline",
"summary": "Update pipeline",
"description": "Rename a pipeline. Only the name can be changed here; stages have their own endpoints.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdatePipeline"
}
}
}
},
"responses": {
"200": {
"description": "Updated pipeline.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pipeline"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "crm_delete_pipeline",
"summary": "Delete pipeline",
"description": "Delete a pipeline and its stages.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Pipeline deleted."
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/pipelines/{id}/stages": {
"post": {
"operationId": "crm_create_stage",
"summary": "Create stage",
"description": "Append a stage to a pipeline.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreatePipelineStage"
}
}
}
},
"responses": {
"201": {
"description": "Created stage.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PipelineStage"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/pipelines/{id}/stages/{stageId}": {
"patch": {
"operationId": "crm_update_stage",
"summary": "Update stage",
"description": "Rename or recolor a stage.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "stageId",
"in": "path",
"required": true,
"description": "Stage ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdatePipelineStage"
}
}
}
},
"responses": {
"200": {
"description": "Updated stage.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PipelineStage"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline or stage not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "crm_delete_stage",
"summary": "Delete stage",
"description": "Remove a stage from a pipeline.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Pipeline ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "stageId",
"in": "path",
"required": true,
"description": "Stage ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Stage deleted."
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Pipeline or stage not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/deals": {
"get": {
"operationId": "crm_list_deals",
"summary": "List deals",
"description": "List deals with optional pipeline, stage, and status filters, keyset-paginated.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "pipeline_id",
"in": "query",
"required": false,
"description": "Restrict to deals in this pipeline.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "stage_id",
"in": "query",
"required": false,
"description": "Restrict to deals in this stage.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "status",
"in": "query",
"required": false,
"description": "Restrict to a deal status.",
"schema": {
"type": "string",
"enum": [
"open",
"won",
"lost"
]
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque keyset cursor from a previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
}
],
"responses": {
"200": {
"description": "Page of deals.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DealList"
}
}
}
},
"400": {
"description": "Invalid cursor, limit, or filter value.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "crm_create_deal",
"summary": "Create deal",
"description": "Create a deal in a pipeline stage, optionally linked to a contact and attributed to a campaign and source mailbox. New deals default to status open.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateDeal"
}
}
}
},
"responses": {
"201": {
"description": "Created deal.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Deal"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/deals/search": {
"post": {
"operationId": "crm_search_deals",
"summary": "Search deals",
"description": "Faceted, offset-paginated deal search. Every filter is optional; an empty body matches every deal in the organization. Filters go in the JSON body; limit and offset are query params.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque cursor from a previous response's pagination.next_cursor. Omit for the first page.",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchDeals"
}
}
}
},
"responses": {
"200": {
"description": "Offset-paginated deal results with an exact total.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DealsSearchResult"
}
}
}
},
"400": {
"description": "Invalid limit, offset, or filter body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/deals/summary": {
"post": {
"operationId": "crm_deals_summary",
"summary": "Deals summary",
"description": "Aggregate counts and value sums over the same filter body as deal search, including per-stage totals. All facets are optional.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchDeals"
}
}
}
},
"responses": {
"200": {
"description": "Aggregate deal totals.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DealsSummary"
}
}
}
},
"400": {
"description": "Invalid filter body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/deals/{id}": {
"get": {
"operationId": "crm_get_deal",
"summary": "Get deal",
"description": "Fetch a single deal. Joined contact, stage, and campaign_name are only populated by the list and search queries, not by this single-row read.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Deal ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The deal.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Deal"
}
}
}
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Deal not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "crm_update_deal",
"summary": "Update deal",
"description": "Update a deal. Moving it to a different stage_id records a stage-change activity, and setting status to won or lost stamps the corresponding close timestamp.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Deal ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateDeal"
}
}
}
},
"responses": {
"200": {
"description": "Updated deal.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Deal"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Deal not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "crm_delete_deal",
"summary": "Delete deal",
"description": "Delete a deal.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Deal ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deal deleted."
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Deal not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/task-types": {
"get": {
"operationId": "crm_list_task_types",
"summary": "List task types",
"description": "List the organization's CRM task types. A default set is seeded the first time an org lists its types. Returns a data array with no pagination envelope.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Task types.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTaskTypeList"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "crm_create_task_type",
"summary": "Create task type",
"description": "Create a CRM task type.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateCRMTaskType"
}
}
}
},
"responses": {
"201": {
"description": "Created task type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTaskType"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/task-types/{id}": {
"patch": {
"operationId": "crm_update_task_type",
"summary": "Update task type",
"description": "Rename, recolor, or reorder a task type.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Task type ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateCRMTaskType"
}
}
}
},
"responses": {
"200": {
"description": "Updated task type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTaskType"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Task type not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "crm_delete_task_type",
"summary": "Delete task type",
"description": "Delete a task type. Tasks reference their type by name, so existing tasks keep their label and fall back to a neutral color rather than being orphaned.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Task type ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Task type deleted."
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Task type not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/tasks": {
"get": {
"operationId": "crm_list_tasks",
"summary": "List tasks",
"description": "List CRM tasks with optional contact, deal, assignee, and status filters, keyset-paginated.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "contact_id",
"in": "query",
"required": false,
"description": "Restrict to tasks linked to this contact.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "deal_id",
"in": "query",
"required": false,
"description": "Restrict to tasks linked to this deal.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "assigned_to",
"in": "query",
"required": false,
"description": "Restrict to tasks assigned to this user.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "status",
"in": "query",
"required": false,
"description": "Restrict to a task status.",
"schema": {
"type": "string",
"enum": [
"pending",
"in_progress",
"completed",
"cancelled"
]
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque keyset cursor from a previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
}
],
"responses": {
"200": {
"description": "Page of tasks.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTaskList"
}
}
}
},
"400": {
"description": "Invalid cursor, limit, or filter value.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "crm_create_task",
"summary": "Create task",
"description": "Create a CRM task, optionally linked to a contact and deal and assigned to a user or team. created_by is set to the authenticated user.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateCRMTask"
}
}
}
},
"responses": {
"201": {
"description": "Created task.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTask"
}
}
}
},
"400": {
"description": "Invalid request body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/tasks/search": {
"post": {
"operationId": "crm_search_tasks",
"summary": "Search tasks",
"description": "Faceted, offset-paginated task search. Every filter is optional; an empty body matches every task in the organization. Filters go in the JSON body; limit and offset are query params.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque cursor from a previous response's pagination.next_cursor. Omit for the first page.",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchTasks"
}
}
}
},
"responses": {
"200": {
"description": "Offset-paginated task results with an exact total.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TasksSearchResult"
}
}
}
},
"400": {
"description": "Invalid limit, offset, or filter body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/tasks/summary": {
"post": {
"operationId": "crm_tasks_summary",
"summary": "Tasks summary",
"description": "Aggregate counts over the same filter body as task search (by status, overdue, high priority). All facets are optional.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SearchTasks"
}
}
}
},
"responses": {
"200": {
"description": "Aggregate task counts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TasksSummary"
}
}
}
},
"400": {
"description": "Invalid filter body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/crm/tasks/{id}": {
"get": {
"operationId": "crm_get_task",
"summary": "Get task",
"description": "Fetch a single CRM task.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Task ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The task.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTask"
}
}
}
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Task not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "crm_update_task",
"summary": "Update task",
"description": "Update a CRM task. Setting status to completed stamps the completion timestamp.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Task ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateCRMTask"
}
}
}
},
"responses": {
"200": {
"description": "Updated task.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CRMTask"
}
}
}
},
"400": {
"description": "Invalid request body or path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Task not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "crm_delete_task",
"summary": "Delete task",
"description": "Delete a CRM task.",
"tags": [
"crm"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Task ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Task deleted."
},
"400": {
"description": "Malformed path parameter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Task not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys": {
"get": {
"operationId": "api-keys_list",
"summary": "List API keys",
"description": "Returns the organization's API keys, newest first. The plaintext secret is never included.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination token from the previous page's pagination.next_cursor. Omit for the first page.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 100. Defaults to 50.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 50
}
}
],
"responses": {
"200": {
"description": "A page of API keys.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyList"
}
}
}
},
"400": {
"description": "Invalid cursor or limit, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "api-keys_create",
"summary": "Create an API key",
"description": "Creates a new key and returns the plaintext secret exactly once. Unknown permission bits are rejected.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateAPIKey"
}
}
}
},
"responses": {
"201": {
"description": "The created key, including the one-time secret.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyWithSecret"
}
}
}
},
"400": {
"description": "Invalid body, no organization selected, or permission bitmask contains unknown bits.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/permissions": {
"get": {
"operationId": "api-keys_list_permissions",
"summary": "List available permissions",
"description": "Returns the catalog of permission bits plus the read_only and full_access presets.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The permission catalog and presets.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIPermissionCatalog"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/usage/summary": {
"get": {
"operationId": "api-keys_usage_summary",
"summary": "Usage summary",
"description": "Org-level usage strip: key counts by status plus a 24-hour request, error, and latency rollup.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The usage summary object.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyUsageSummary"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/usage/analytics": {
"get": {
"operationId": "api-keys_usage_analytics",
"summary": "Org-wide usage analytics",
"description": "Time-bucketed request series plus a per-endpoint breakdown for the whole organization. For this org-wide form api_key_id is the all-zero UUID.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "from",
"in": "query",
"required": false,
"description": "Start of the window (RFC3339). Defaults to 24 hours before to.",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "to",
"in": "query",
"required": false,
"description": "End of the window (RFC3339). Defaults to now.",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "interval",
"in": "query",
"required": false,
"description": "Bucket granularity.",
"schema": {
"type": "string",
"enum": [
"minute",
"hour",
"day"
]
}
}
],
"responses": {
"200": {
"description": "The analytics payload.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyAnalytics"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/{id}": {
"get": {
"operationId": "api-keys_get",
"summary": "Get an API key",
"description": "Returns a single key by id. The secret is never included.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKey"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "api-keys_update",
"summary": "Update an API key",
"description": "Updates the mutable fields of a key. Every field is optional; only the fields you send are changed. The secret cannot be rotated here.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateAPIKey"
}
}
}
},
"responses": {
"200": {
"description": "The updated API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKey"
}
}
}
},
"400": {
"description": "Invalid body, no organization selected, or permission bitmask contains unknown bits.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "api-keys_revoke",
"summary": "Revoke an API key",
"description": "Revokes a key immediately. The key stops authenticating right away; this is not reversible.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "reason",
"in": "query",
"required": false,
"description": "Optional revocation note stored on the key. Defaults to \"Revoked by user\".",
"schema": {
"type": "string"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Revocation status envelope.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyRevokeResult"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/{id}/permanent": {
"delete": {
"operationId": "api-keys_delete",
"summary": "Delete an API key",
"description": "Removes a revoked or expired key from the workspace for good, along with its usage logs. A key that could still authenticate is refused with a 409: revoke it first, so what ended the credential stays on the record. A key past its expires_at can be deleted directly, since it already authenticates nothing.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Deletion status envelope.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyDeleteResult"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"409": {
"description": "The key can still authenticate. Revoke it first.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/{id}/analytics": {
"get": {
"operationId": "api-keys_analytics",
"summary": "Per-key usage analytics",
"description": "Time-bucketed request series plus a per-endpoint breakdown for a single key. Pass the literal id value `all` for the org-wide aggregate.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The API key id, or the literal `all` for the org-wide aggregate.",
"schema": {
"type": "string"
}
},
{
"name": "from",
"in": "query",
"required": false,
"description": "Start of the window (RFC3339). Defaults to 24 hours before to.",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "to",
"in": "query",
"required": false,
"description": "End of the window (RFC3339). Defaults to now.",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "interval",
"in": "query",
"required": false,
"description": "Bucket granularity.",
"schema": {
"type": "string",
"enum": [
"minute",
"hour",
"day"
]
}
}
],
"responses": {
"200": {
"description": "The analytics payload.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyAnalytics"
}
}
}
},
"400": {
"description": "No organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID (when not `all`) or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/api-keys/{id}/logs": {
"get": {
"operationId": "api-keys_list_logs",
"summary": "List per-key usage logs",
"description": "Returns the recent raw request entries for a single key, newest first.",
"tags": [
"api-keys"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination token from the previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200. Defaults to 50.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
}
],
"responses": {
"200": {
"description": "A page of usage log entries.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/APIKeyUsageLogList"
}
}
}
},
"400": {
"description": "Invalid cursor, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthenticated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing API_KEYS scope or manage_api_keys org permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Invalid UUID or key not found in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/webhooks": {
"get": {
"operationId": "webhooks_list",
"tags": [
"webhooks"
],
"summary": "List webhook endpoints",
"description": "Returns every webhook endpoint configured for the caller's organization, plus the canonical `event_types` vocabulary for building a picker. Secrets are never returned. This endpoint does NOT use the `data` + `pagination` cursor envelope. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The organization's webhook endpoints and the full event vocabulary.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpointList"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "webhooks_create",
"tags": [
"webhooks"
],
"summary": "Create a webhook endpoint",
"description": "Creates a new event subscription. The `url` must be HTTPS and resolve to a publicly routable host (loopback, private, and link-local targets are rejected unless the server runs with unsafe webhook URLs enabled for local or self-hosted development). The response is the only time the signing `secret` (prefixed `whsec_`) is returned, so capture it immediately. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpointRequest"
}
}
}
},
"responses": {
"201": {
"description": "The created endpoint, including the one-time `secret`.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpointWithSecret"
}
}
}
},
"400": {
"description": "Invalid payload, non-HTTPS or non-routable url, or unknown event type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/webhooks/{id}": {
"patch": {
"operationId": "webhooks_update",
"tags": [
"webhooks"
],
"summary": "Update a webhook endpoint",
"description": "Replaces the endpoint's url, description, event filter, and enabled state with the values sent (send the complete desired state; `event_types` is overwritten, not merged). The signing secret is not changed here; use the rotate-secret endpoint. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The endpoint id to update.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpointRequest"
}
}
}
},
"responses": {
"200": {
"description": "The updated endpoint (no secret).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpoint"
}
}
}
},
"400": {
"description": "Invalid payload, invalid endpoint id, non-HTTPS or non-routable url, or unknown event type.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Endpoint not found or not owned by your organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "webhooks_delete",
"tags": [
"webhooks"
],
"summary": "Delete a webhook endpoint",
"description": "Deletes a subscription and cascades to its delivery history. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The endpoint id to delete.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deleted. Empty body."
},
"400": {
"description": "Invalid endpoint id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Endpoint not found or not owned by your organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/webhooks/{id}/rotate-secret": {
"post": {
"operationId": "webhooks_rotate_secret",
"tags": [
"webhooks"
],
"summary": "Rotate the signing secret",
"description": "Issues a new HMAC signing secret and returns it once. In-flight deliveries already signed continue to verify against the old secret until they settle; new deliveries use the new secret. Update your `X-Warmbly-Signature` verifier promptly. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The endpoint id to rotate.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "The new signing secret. Returned only once.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookSecretResponse"
}
}
}
},
"400": {
"description": "Invalid endpoint id.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Endpoint not found or not owned by your organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/webhooks/{id}/deliveries": {
"get": {
"operationId": "webhooks_list_deliveries",
"tags": [
"webhooks"
],
"summary": "List delivery attempts",
"description": "Returns recent delivery attempts for an endpoint, newest first. Each row updates in place across retries, so an event that retried several times appears as one record whose `attempt_count` and `status` reflect the latest state. This endpoint does NOT use the `data` + `pagination` cursor envelope; it returns a `deliveries` array bounded by `limit`. Requires the `WEBHOOKS` scope and the `manage_settings` org permission.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The endpoint id whose deliveries to list.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Max rows to return. Between 1 and 200. Defaults to 50. Out-of-range values return 400.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 50
}
}
],
"responses": {
"200": {
"description": "Recent delivery attempts for the endpoint.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookDeliveryList"
}
}
}
},
"400": {
"description": "Invalid endpoint id or a limit outside 1 to 200.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Endpoint not found or not owned by your organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/dashboard": {
"get": {
"operationId": "analytics_dashboard",
"tags": [
"analytics"
],
"summary": "Get dashboard analytics",
"description": "Org-wide dashboard overview: aggregate stats, recent activity, top campaigns, account health, and a daily trend series.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "period",
"in": "query",
"required": false,
"description": "One of 7d, 30d, 90d. Any other value falls back to 7d.",
"schema": {
"type": "string",
"enum": [
"7d",
"30d",
"90d"
],
"default": "7d"
}
}
],
"responses": {
"200": {
"description": "Dashboard analytics overview.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DashboardAnalytics"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/deliverability": {
"get": {
"operationId": "analytics_deliverability",
"tags": [
"analytics"
],
"summary": "Get deliverability dashboard",
"description": "Deliverability posture over a window: bounce/complaint/open/click/reply counts and rates, suppression and dead-letter pressure, reply-intent breakdown, seed inbox-placement, health band, daily timeseries, and per-mailbox/per-campaign breakdowns.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "from",
"in": "query",
"required": false,
"description": "Window start as an RFC 3339 timestamp. Defaults to 7 days ago (UTC).",
"schema": {
"type": "string",
"format": "date-time"
}
},
{
"name": "to",
"in": "query",
"required": false,
"description": "Window end as an RFC 3339 timestamp. Defaults to now (UTC).",
"schema": {
"type": "string",
"format": "date-time"
}
}
],
"responses": {
"200": {
"description": "Deliverability dashboard.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeliverabilityDashboard"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/warmup": {
"get": {
"operationId": "analytics_warmup",
"tags": [
"analytics"
],
"summary": "Get warmup analytics",
"description": "Warmup send and reply statistics over a date range, with a summary and per-day series. Optionally scoped to a single mailbox.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "from",
"in": "query",
"required": true,
"description": "Range start (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "to",
"in": "query",
"required": true,
"description": "Range end (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "email_id",
"in": "query",
"required": false,
"description": "Limit to one email account. Invalid UUIDs are ignored.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Warmup analytics.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupAnalytics"
}
}
}
},
"400": {
"description": "Missing or invalid range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/campaigns/compare": {
"get": {
"operationId": "analytics_campaigns_compare",
"tags": [
"analytics"
],
"summary": "Compare campaigns",
"description": "Side-by-side performance for up to 10 campaigns over a date range. Every requested campaign must belong to the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "ids",
"in": "query",
"required": true,
"description": "Comma-separated campaign UUIDs. Invalid entries are dropped; capped at 10. At least one valid id is required.",
"schema": {
"type": "string"
}
},
{
"name": "from",
"in": "query",
"required": true,
"description": "Range start (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "to",
"in": "query",
"required": true,
"description": "Range end (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
}
],
"responses": {
"200": {
"description": "Campaign comparison.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignComparison"
}
}
}
},
"400": {
"description": "Missing or invalid ids/range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "A requested campaign was not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/campaigns/{id}": {
"get": {
"operationId": "analytics_campaign_get",
"tags": [
"analytics"
],
"summary": "Get campaign analytics",
"description": "A single campaign's performance summary plus per-step stats. The campaign must belong to the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Campaign id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Campaign analytics.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignAnalytics"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Campaign not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/campaigns/{id}/daily": {
"get": {
"operationId": "analytics_campaign_daily",
"tags": [
"analytics"
],
"summary": "Get campaign daily stats",
"description": "Per-day send, open, click, and reply counts for one campaign over a date range. The campaign must belong to the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Campaign id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "from",
"in": "query",
"required": true,
"description": "Range start (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "to",
"in": "query",
"required": true,
"description": "Range end (YYYY-MM-DD).",
"schema": {
"type": "string",
"format": "date"
}
}
],
"responses": {
"200": {
"description": "Per-day series under a data envelope.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignDailyStats"
}
}
}
},
"400": {
"description": "Missing or invalid range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Campaign not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/campaigns/{id}/hourly": {
"get": {
"operationId": "analytics_campaign_hourly",
"tags": [
"analytics"
],
"summary": "Get campaign hourly stats",
"description": "Per-hour stats for one campaign on a single day. The campaign must belong to the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Campaign id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "date",
"in": "query",
"required": false,
"description": "Day to report (YYYY-MM-DD). Defaults to today.",
"schema": {
"type": "string",
"format": "date"
}
}
],
"responses": {
"200": {
"description": "Per-hour series under a data envelope with the resolved date echoed back.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CampaignHourlyStats"
}
}
}
},
"400": {
"description": "Invalid date.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Campaign not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/accounts": {
"get": {
"operationId": "analytics_accounts_list",
"tags": [
"analytics"
],
"summary": "List account statuses",
"description": "Health and usage status of every email account the caller owns. Returned under a data envelope (no cursor; all accounts included). Accounts that fail to build are skipped.",
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Account statuses.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AccountStatusList"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/accounts/{id}": {
"get": {
"operationId": "analytics_account_get",
"tags": [
"analytics"
],
"summary": "Get account status",
"description": "Detailed status for one email account: combined health score (folding in warmup-pool reputation), active errors, today's usage, warmup status, and warmup-pool health. The account must belong to the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "Email account id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Account status detail.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AccountStatusDetail"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Account not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/analytics/usage": {
"get": {
"operationId": "analytics_usage",
"tags": [
"analytics"
],
"summary": "Get usage overview",
"description": "Account, campaign, contact, and API usage counters for the caller.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "period",
"in": "query",
"required": false,
"description": "One of day, week, month. Any other value falls back to day.",
"schema": {
"type": "string",
"enum": [
"day",
"week",
"month"
],
"default": "day"
}
}
],
"responses": {
"200": {
"description": "Usage overview.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UsageOverview"
}
}
}
},
"400": {
"description": "Invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/audit-logs": {
"get": {
"operationId": "analytics_audit_logs_list",
"tags": [
"analytics"
],
"summary": "List audit logs",
"description": "Organization-wide activity trail for the caller's current organization. The organization is always taken from the session, never from a parameter. Auth: scope READ_AUDIT_LOGS, org permission view_analytics.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size. Defaults to 50; must be between 10 and 200 or a 400 is returned.",
"schema": {
"type": "integer",
"minimum": 10,
"maximum": 200,
"default": 50
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque cursor from pagination.next_cursor. Invalid cursors return 400.",
"schema": {
"type": "string"
}
},
{
"name": "actor_id",
"in": "query",
"required": false,
"description": "Filter to a single acting member.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "entity_id",
"in": "query",
"required": false,
"description": "Filter to a single entity.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "entity_type",
"in": "query",
"required": false,
"description": "Filter by entity type (for example campaign, contact, email_account, api_key, webhook).",
"schema": {
"type": "string"
}
},
{
"name": "action",
"in": "query",
"required": false,
"description": "Filter by action (for example create, update, delete, send, revoke).",
"schema": {
"type": "string"
}
},
{
"name": "date",
"in": "query",
"required": false,
"description": "Single-day filter (YYYY-MM-DD), expanded to that whole UTC day.",
"schema": {
"type": "string",
"format": "date"
}
},
{
"name": "start_date",
"in": "query",
"required": false,
"description": "Range start. RFC 3339 or YYYY-MM-DD. Overrides date.",
"schema": {
"type": "string"
}
},
{
"name": "end_date",
"in": "query",
"required": false,
"description": "Range end. RFC 3339 or YYYY-MM-DD. Overrides date.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Audit log page (data plus pagination).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AuditLogList"
}
}
}
},
"400": {
"description": "Invalid cursor, limit, or filter.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Insufficient permissions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/catalog": {
"get": {
"operationId": "integrations_catalog_list",
"summary": "List the integration catalog",
"description": "Static metadata for every provider Warmbly supports, annotated with whether each OAuth provider has server-side credentials wired (`configured`).",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Provider catalog.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationCatalogList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (missing INTEGRATIONS scope).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections": {
"get": {
"operationId": "integrations_connections_list",
"summary": "List connections",
"description": "This org's connection rows. Secrets are never serialized. Returns a bare `connections` array, not the cursor-paginated envelope.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Connections.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationConnectionList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "integrations_connections_create",
"summary": "Create a connection",
"description": "Creates a credential-based connection for `api_key` / `webhook` providers (e.g. Close, Discord). OAuth providers are rejected with a hint to start the authorize flow instead. Inbound providers (Calendly, Cal.com) include `inbound_webhook_url` once. Requires the `manage_settings` org permission for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationConnectionCreate"
}
}
}
},
"responses": {
"201": {
"description": "Connection created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationConnection"
}
}
}
},
"400": {
"description": "Bad request (e.g. OAuth provider, invalid provider).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (paid-plan feature or missing permission).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}": {
"get": {
"operationId": "integrations_connections_get",
"summary": "Get a connection",
"description": "One connection plus its event subscriptions and up to 20 recent sync runs.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"responses": {
"200": {
"description": "Connection detail.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationConnectionDetail"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "integrations_connections_delete",
"summary": "Disconnect",
"description": "Removes a connection row. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Disconnected."
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/config": {
"patch": {
"operationId": "integrations_connections_update_config",
"summary": "Update connection config",
"description": "Saves a connection's onboarding/capability snapshot and its sync direction. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationConnectionConfigUpdate"
}
}
}
},
"responses": {
"200": {
"description": "Updated connection.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"connection"
],
"properties": {
"connection": {
"$ref": "#/components/schemas/IntegrationConnection"
}
}
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/events": {
"get": {
"operationId": "integrations_event_subscriptions_list",
"summary": "List event subscriptions",
"description": "The event-to-action routes configured on a connection.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"responses": {
"200": {
"description": "Event subscriptions.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationEventSubscriptionList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "integrations_event_subscriptions_create",
"summary": "Create an event subscription",
"description": "Routes a Warmbly event to a provider action on this connection. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationEventSubscriptionCreate"
}
}
}
},
"responses": {
"201": {
"description": "Event subscription created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationEventSubscription"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (paid-plan feature or missing permission).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/events/{eventId}": {
"delete": {
"operationId": "integrations_event_subscriptions_delete",
"summary": "Delete an event subscription",
"description": "Removes one event subscription. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
},
{
"name": "eventId",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Event subscription id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Deleted."
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/field-mappings": {
"get": {
"operationId": "integrations_field_mappings_list",
"summary": "List field mappings",
"description": "The Warmbly-field to provider-field maps configured for a connection.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"responses": {
"200": {
"description": "Field mappings.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationFieldMappingList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"put": {
"operationId": "integrations_field_mappings_replace",
"summary": "Replace field mappings",
"description": "Swaps the connection-default field map for an object wholesale. A full replace is naturally idempotent so no `Idempotency-Key` is required. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationFieldMappingReplace"
}
}
}
},
"responses": {
"200": {
"description": "Full mapping set after the replace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationFieldMappingList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/runs": {
"get": {
"operationId": "integrations_sync_runs_list",
"summary": "List sync runs",
"description": "Up to 50 recent observability records for a connection (connect, token refresh, event dispatch, manual push).",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"responses": {
"200": {
"description": "Sync runs.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationSyncRunList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/webhook-secret": {
"get": {
"operationId": "integrations_webhook_secret_get",
"summary": "Get the connection webhook secret",
"description": "Returns (generating on first call) the HMAC signing secret for an automation connection so you can verify Warmbly's outbound webhook signatures. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"responses": {
"200": {
"description": "Signing secret.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationWebhookSecret"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/test": {
"post": {
"operationId": "integrations_connection_test",
"summary": "Test a connection",
"description": "Fires a synthetic event through the connection's notify/webhook automations so you can confirm the channel is wired. Requires `manage_settings` for JWT callers.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Test event dispatched.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"sent"
],
"properties": {
"sent": {
"type": "boolean"
}
}
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/connections/{id}/push": {
"post": {
"operationId": "integrations_connection_push",
"summary": "Push contacts to a CRM",
"description": "Synchronously upserts the given org contacts into a connected CRM (HubSpot, Pipedrive, Salesforce, Close). Retries are naturally safe (every upsert is keyed by email), so no `Idempotency-Key` is required. Requires the `use_integrations` org permission for JWT callers. A connection whose token can no longer be refreshed returns 409.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Connection id."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationPushRequest"
}
}
}
},
"responses": {
"200": {
"description": "Per-record push results.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IntegrationPushResult"
}
}
}
},
"400": {
"description": "A selection that names nothing, an exclusion list over 50000 or one resolving to more than 500 contacts (`too_many_contacts`), a select-all with no filters, a filter matching no contacts, or a filter matching more than 50000 (`selection_too_large`).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (paid-plan feature or missing permission).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Connection or matching contacts not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"409": {
"description": "Connection needs to be reconnected (token not refreshable).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/integrations/bookings": {
"get": {
"operationId": "integrations_bookings_list",
"summary": "List meeting bookings (integrations view)",
"description": "Up to 50 recent booked meetings, surfaced on the integrations page. For the full Meetings list with filters and pagination, use `GET /meetings`.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Recent bookings.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MeetingBookingList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/automations": {
"get": {
"operationId": "automations_list",
"summary": "List automations",
"description": "This org's automation flows (the visual flow builder). Returns a bare `automations` array.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Automations.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "automations_create",
"summary": "Create an automation",
"description": "Creates a new automation flow: a trigger event plus a graph of condition and action nodes. Action nodes may reference provider actions (e.g. `slack.notify`, `hubspot.upsert_contact`) or Warmbly-native actions (e.g. `warmbly.add_tag`, `warmbly.label_email`) that need no external connection.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationWrite"
}
}
}
},
"responses": {
"201": {
"description": "Automation created.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"automation"
],
"properties": {
"automation": {
"$ref": "#/components/schemas/Automation"
}
}
}
}
}
},
"400": {
"description": "Bad request (invalid graph, missing trigger).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (paid-plan feature or missing permission).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/automations/{id}": {
"get": {
"operationId": "automations_get",
"summary": "Get an automation",
"description": "One automation with its full graph.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Automation id."
}
],
"responses": {
"200": {
"description": "Automation.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"automation"
],
"properties": {
"automation": {
"$ref": "#/components/schemas/Automation"
}
}
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "automations_update",
"summary": "Update an automation",
"description": "Replaces an automation's name, enabled state, trigger, filter, and graph. The body shape matches the create payload.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Automation id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationWrite"
}
}
}
},
"responses": {
"200": {
"description": "Updated automation.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"automation"
],
"properties": {
"automation": {
"$ref": "#/components/schemas/Automation"
}
}
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "automations_delete",
"summary": "Delete an automation",
"description": "Removes an automation. Returns 409 when the automation is still referenced by campaign steps.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Automation id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Deleted.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"deleted"
],
"properties": {
"deleted": {
"type": "boolean"
}
}
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"409": {
"description": "Still referenced by campaign steps.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/automations/{id}/test": {
"post": {
"operationId": "automations_test",
"summary": "Test an automation",
"description": "Runs the automation against sample (or provided) data without side effects and returns the walked trace plus per-action previews.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Automation id."
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationDryRunRequest"
}
}
}
},
"responses": {
"200": {
"description": "Dry-run trace plus resolved event data.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationDryRunResponse"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/automations/{id}/runs": {
"get": {
"operationId": "automations_runs_list",
"summary": "List automation runs",
"description": "Recent run history for an automation (per fired event or manual launch), with per-node outcomes.",
"tags": [
"integrations"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Automation id."
},
{
"name": "limit",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"default": 50
},
"description": "Max runs to return. Defaults to 50."
}
],
"responses": {
"200": {
"description": "Automation runs.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AutomationRunList"
}
}
}
},
"400": {
"description": "Bad request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/teams": {
"get": {
"operationId": "account-org_teams_list",
"summary": "List teams",
"description": "Returns the current organization's teams, each hydrated with its members. Requires a selected organization.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The organization's teams.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamCollection"
}
}
}
},
"400": {
"description": "No organization selected or invalid request.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the READ_CRM scope or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "account-org_teams_create",
"summary": "Create a team",
"description": "Creates a team (members start empty). Requires a selected organization.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamCreate"
}
}
}
},
"responses": {
"201": {
"description": "The created team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Team"
}
}
}
},
"400": {
"description": "Validation error or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the WRITE_CRM scope or caller lacks manage_team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/teams/{id}": {
"get": {
"operationId": "account-org_teams_get",
"summary": "Get a team",
"description": "Returns a single team with its members.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The team id.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Team"
}
}
}
},
"400": {
"description": "Invalid id or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the READ_CRM scope or caller lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Team not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "account-org_teams_update",
"summary": "Update a team",
"description": "Partial-updates a team's name or color. Omitted fields are left untouched.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The team id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamUpdate"
}
}
}
},
"responses": {
"200": {
"description": "The updated team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Team"
}
}
}
},
"400": {
"description": "Validation error, invalid id, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the WRITE_CRM scope or caller lacks manage_team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Team not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "account-org_teams_delete",
"summary": "Delete a team",
"description": "Deletes a team.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The team id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Team deleted."
},
"400": {
"description": "Invalid id or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the WRITE_CRM scope or caller lacks manage_team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Team not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/teams/{id}/members": {
"post": {
"operationId": "account-org_teams_add_member",
"summary": "Add a team member",
"description": "Adds an existing organization member to the team and returns the updated team.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The team id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TeamAddMember"
}
}
}
},
"responses": {
"200": {
"description": "The updated team, including the new member.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Team"
}
}
}
},
"400": {
"description": "Validation error, invalid id, or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the WRITE_CRM scope or caller lacks manage_team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Team not found, or the user is not an organization member.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/teams/{id}/members/{userId}": {
"delete": {
"operationId": "account-org_teams_remove_member",
"summary": "Remove a team member",
"description": "Removes a member from the team.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The team id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "userId",
"in": "path",
"required": true,
"description": "The member's user id.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Member removed."
},
"400": {
"description": "Invalid id or no organization selected.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Key lacks the WRITE_CRM scope or caller lacks manage_team.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Team or membership not found.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/plans": {
"get": {
"operationId": "account-org_plans_list",
"summary": "List plans",
"description": "Returns the available public subscription plans. Open to any authenticated caller (JWT or API key); auth exists only to deter scraping.",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The public subscription plans.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PlanList"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/timezones": {
"get": {
"operationId": "account-org_timezones_list",
"summary": "List timezones",
"description": "Returns the supported timezone identifiers (for campaign schedule windows and the like). Open to any authenticated caller (JWT or API key).",
"tags": [
"account-org"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The supported timezones, sorted by UTC offset.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TimezoneOption"
}
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/outreach/settings": {
"get": {
"operationId": "deliverability-ops_get_settings",
"summary": "Get outreach settings",
"description": "Returns the organization's advanced outreach settings (bounce pipeline, task reliability, A/B testing, reply-intent, send-time optimization, preflight, dashboard).",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "The advanced outreach settings object (not envelope-wrapped).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdvancedOutreachSettings"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden (missing WRITE_CAMPAIGNS scope or manage_settings permission)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "deliverability-ops_update_settings",
"summary": "Update outreach settings",
"description": "Replaces the organization's advanced outreach settings with the supplied object (upserted, not deep-merged). Returns no body.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpsertOutreachSettingsRequest"
}
}
}
},
"responses": {
"204": {
"description": "Settings updated"
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/deliverability/events": {
"post": {
"operationId": "deliverability-ops_ingest_event",
"summary": "Ingest a deliverability event",
"description": "Posts a single deliverability signal (bounce, complaint, unsubscribe, open, click, reply) into the platform. API-key callable so downstream pipelines can report events. Supply idempotency_key to make retries safe. Requires WRITE_CAMPAIGNS scope and send_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IngestDeliverabilityEventRequest"
}
}
}
},
"responses": {
"202": {
"description": "Event accepted and queued for processing (no body)."
},
"400": {
"description": "Invalid event payload (e.g. missing event_type or recipient_email)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tasks/dlq": {
"get": {
"operationId": "deliverability-ops_list_dead_letters",
"summary": "List task dead letters",
"description": "Lists tasks that exhausted their retry budget and landed in the dead-letter queue. Not cursor-paginated: returns up to `limit` rows in one response. Requires SEND_CAMPAIGNS scope and send_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "status",
"in": "query",
"required": false,
"description": "Optional status filter (e.g. pending, replayed).",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Max rows to return, 1 to 200 (default 100).",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"default": 100
}
}
],
"responses": {
"200": {
"description": "Dead-letter records under a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TaskDeadLetterList"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tasks/dlq/{id}/replay": {
"post": {
"operationId": "deliverability-ops_replay_dead_letter",
"summary": "Replay a task dead letter",
"description": "Re-dispatches a dead-lettered task. Because a replay can transmit real mail this requires SEND_CAMPAIGNS scope and send_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The dead-letter record ID (the `id` field, not `task_id`).",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "Replay dispatched.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplayDeadLetterResponse"
}
}
}
},
"400": {
"description": "Invalid dead-letter id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Dead-letter record not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/warmup/routing": {
"get": {
"operationId": "deliverability-ops_list_routing_rules",
"summary": "List warmup routing rules",
"description": "Returns every warmup routing rule for the organization, ordered by priority ascending. Not cursor-paginated. Requires WARMUP_ROUTING scope and manage_settings permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Routing rules under a `rules` array (never null).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupRoutingRuleList"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "deliverability-ops_create_routing_rule",
"summary": "Create a warmup routing rule",
"description": "Creates a routing rule for the organization. Both sender and recipient sides are matched; a rule applies only when both match. Match values are lowercased and trimmed on write. Requires WARMUP_ROUTING scope and manage_settings permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupRoutingRuleInput"
}
}
}
},
"responses": {
"201": {
"description": "Rule created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupRoutingRule"
}
}
}
},
"400": {
"description": "Invalid payload (e.g. missing name, bad match type, missing required match value, negative weight)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/warmup/routing/{id}": {
"patch": {
"operationId": "deliverability-ops_update_routing_rule",
"summary": "Update a warmup routing rule",
"description": "Replaces a rule by ID. The body is the same full payload as create (all fields applied, not deep-merged). Requires WARMUP_ROUTING scope and manage_settings permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The rule ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupRoutingRuleInput"
}
}
}
},
"responses": {
"200": {
"description": "Rule updated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WarmupRoutingRule"
}
}
}
},
"400": {
"description": "Invalid payload or rule id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Rule not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "deliverability-ops_delete_routing_rule",
"summary": "Delete a warmup routing rule",
"description": "Removes a routing rule by ID. Requires WARMUP_ROUTING scope and manage_settings permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The rule ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Rule deleted"
},
"400": {
"description": "Invalid rule id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Rule not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates": {
"get": {
"operationId": "deliverability-ops_list_templates",
"summary": "List reply templates",
"description": "Lists the organization's reply templates, ordered by position. Optional `q` filter matches name and subject (case-insensitive). Not cursor-paginated. Requires READ_TEMPLATES scope and view_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": false,
"description": "Optional case-insensitive search over name and subject.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Reply templates under a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplateList"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"operationId": "deliverability-ops_create_template",
"summary": "Create a reply template",
"description": "Creates a reply template owned by the calling user, appended to the end of the org's list. Requires WRITE_TEMPLATES scope and manage_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateReplyTemplate"
}
}
}
},
"responses": {
"200": {
"description": "Template created.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplate"
}
}
}
},
"400": {
"description": "Invalid payload (e.g. missing name or name over 255 chars)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/reorder": {
"patch": {
"operationId": "deliverability-ops_reorder_templates",
"summary": "Reorder reply templates",
"description": "Repositions templates to match the supplied ID order (1-indexed). IDs omitted from the list are left untouched. Returns the full reordered list. Requires WRITE_TEMPLATES scope and manage_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReorderReplyTemplates"
}
}
}
},
"responses": {
"200": {
"description": "Reordered list under a `data` array.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplateList"
}
}
}
},
"400": {
"description": "Invalid payload (e.g. missing ids)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/analyze": {
"post": {
"operationId": "deliverability-ops_analyze_template",
"summary": "Analyze template content with AI",
"description": "Runs the deployment's configured AI provider over a subject and body and returns the specific words and sentences that hurt deliverability, quoted from the copy, with whether each one is in the subject or the body and what to write instead. The rules-based score runs in the same request and comes back under `rules`. Advisory only and never blocks sending. Spends AI credits; honors `Idempotency-Key`. Requires WRITE_TEMPLATES scope (it writes no template, but a read-only key must not be able to spend the workspace credits), and the view_campaigns and use_ai permissions.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "Makes a retry safe: the same key is never charged twice.",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ScoreTemplateRequest"
}
}
}
},
"responses": {
"200": {
"description": "The analysis, with the rules-based pass alongside it.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateAnalysis"
}
}
}
},
"400": {
"description": "Nothing written to analyze, or the template is over the size cap",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"402": {
"description": "Out of AI credits. Nothing is charged and no provider call is made.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "No AI provider configured (code `ai_not_configured`, permanent for that deployment), or the provider failed (code `service_unavailable`, and the reserved credits are refunded).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/score": {
"post": {
"operationId": "deliverability-ops_score_template",
"summary": "Score template content",
"description": "Returns an advisory deliverability content score (0 to 100, higher is safer) for a subject and body, plus the issues found. Advisory only and never blocks sending. Scores content in the request body, not a stored template. Requires READ_TEMPLATES scope and view_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ScoreTemplateRequest"
}
}
}
},
"responses": {
"200": {
"description": "Content score and advisory issues.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TemplateScoreResult"
}
}
}
},
"400": {
"description": "Invalid request body",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/{id}": {
"get": {
"operationId": "deliverability-ops_get_template",
"summary": "Get a reply template",
"description": "Retrieves a single reply template by ID. Requires READ_TEMPLATES scope and view_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The template ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "The reply template.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplate"
}
}
}
},
"400": {
"description": "Invalid template id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"patch": {
"operationId": "deliverability-ops_update_template",
"summary": "Update a reply template",
"description": "Updates a reply template. All fields optional; omitted fields are left unchanged. Requires WRITE_TEMPLATES scope and manage_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The template ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateReplyTemplate"
}
}
}
},
"responses": {
"200": {
"description": "Template updated.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplate"
}
}
}
},
"400": {
"description": "Invalid payload or template id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "deliverability-ops_delete_template",
"summary": "Delete a reply template",
"description": "Deletes a reply template by ID. Requires WRITE_TEMPLATES scope and manage_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The template ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"204": {
"description": "Template deleted"
},
"400": {
"description": "Invalid template id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/{id}/duplicate": {
"post": {
"operationId": "deliverability-ops_duplicate_template",
"summary": "Duplicate a reply template",
"description": "Clones a template, appending \" (copy)\" to the name and placing the clone at the end of the org's list. Requires WRITE_TEMPLATES scope and manage_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The source template ID.",
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"responses": {
"200": {
"description": "The newly created template.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReplyTemplate"
}
}
}
},
"400": {
"description": "Invalid template id",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Source template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/templates/{id}/render": {
"post": {
"operationId": "deliverability-ops_render_template",
"summary": "Render a reply template",
"description": "Expands {{.Key}} placeholders in the template's subject and body using a caller-supplied variable map. The body is optional; an empty map renders all placeholders empty. Requires READ_TEMPLATES scope and view_campaigns permission.",
"tags": [
"deliverability-ops"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"description": "The template ID.",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RenderReplyTemplateRequest"
}
}
}
},
"responses": {
"200": {
"description": "The rendered subject and body.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RenderedReplyTemplate"
}
}
}
},
"400": {
"description": "Invalid template id or body",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Template not found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/ai/tools": {
"get": {
"operationId": "ai_tools_list",
"summary": "List agent tools",
"description": "The AI tool registry filtered to what the caller's credentials allow. `format=openai` (aliases `hermes`, `functions`) returns OpenAI function-calling objects; the default returns `{name, description, input_schema}` per tool. Send-class tools are never listed.",
"tags": [
"ai"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "format",
"in": "query",
"required": false,
"description": "Manifest format.",
"schema": {
"type": "string",
"enum": [
"warmbly",
"openai",
"hermes",
"functions"
],
"default": "warmbly"
}
}
],
"responses": {
"200": {
"description": "The permitted tool catalog.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"description": "One tool, shaped by `format`."
}
}
}
}
}
}
},
"400": {
"description": "Unknown format, or no organization for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/ai/tools/{name}/call": {
"post": {
"operationId": "ai_tools_call",
"summary": "Execute an agent tool",
"description": "Runs one registry tool. The request body is the tool's JSON argument object (empty body = no arguments). Each tool enforces its own permission; send-class tools are never callable here.",
"tags": [
"ai"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "name",
"in": "path",
"required": true,
"description": "The tool name from the list endpoint.",
"schema": {
"type": "string"
}
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": false,
"content": {
"application/json": {
"schema": {
"type": "object",
"description": "The tool's argument object, matching its input schema."
}
}
}
},
"responses": {
"200": {
"description": "The tool's output.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "object",
"required": [
"name",
"result"
],
"properties": {
"name": {
"type": "string"
},
"result": {
"description": "The tool's output, embedded as JSON when the tool returned JSON."
}
}
}
}
}
}
}
},
"400": {
"description": "Malformed argument body, or no organization for this key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "The credentials lack the permission for this tool.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Unknown tool.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Tool-level failure; the message is meant for the model to read.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/suppressions": {
"get": {
"tags": [
"deliverability-ops"
],
"operationId": "deliverability-ops_list_suppressions",
"summary": "List the suppression list",
"description": "Pages the workspace suppression list newest first: every address and domain no campaign will email. Scope `READ_CONTACTS`, org permission `view_contacts`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "q",
"in": "query",
"required": false,
"description": "Substring filter on the address or domain.",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Page size, 1 to 200. Default 50.",
"schema": {
"type": "integer"
}
},
{
"name": "cursor",
"in": "query",
"required": false,
"description": "Opaque pagination cursor from the previous page's pagination.next_cursor.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "A page of suppression entries.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SuppressionListResult"
}
}
}
},
"400": {
"description": "Invalid limit or cursor.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks READ_CONTACTS or the member lacks view_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"post": {
"tags": [
"deliverability-ops"
],
"operationId": "deliverability-ops_add_suppressions",
"summary": "Add to the suppression list",
"description": "Adds addresses and domains. Unparseable values are reported in `skipped`; existing entries are updated in place, so the call is safe to repeat. Scope `WRITE_CONTACTS`, org permission `manage_contacts`.",
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddSuppressionsRequest"
}
}
}
},
"responses": {
"200": {
"description": "What the request did.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddSuppressionsResult"
}
}
}
},
"400": {
"description": "No entries, or more than 5000.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or the member lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/suppressions/{id}": {
"delete": {
"tags": [
"deliverability-ops"
],
"operationId": "deliverability-ops_remove_suppression",
"summary": "Remove from the suppression list",
"description": "Lifts one entry so campaigns can email the address (or every address at the domain) again. Recorded in the audit log. Scope `WRITE_CONTACTS`, org permission `manage_contacts`.",
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"204": {
"description": "Entry removed."
},
"400": {
"description": "Invalid suppression ID.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid API key.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "API key lacks WRITE_CONTACTS or the member lacks manage_contacts.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such entry in this organization.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/folders": {
"post": {
"operationId": "labels_create_folder",
"summary": "Create folder",
"description": "Campaign folders. The new entry lands at the end of the workspace's registry. A registry holds at most 100 entries.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The created folder.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour, or the registry is full.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/folders/{id}": {
"patch": {
"operationId": "labels_update_folder",
"summary": "Update folder",
"description": "Rename or recolour a folder. Any member of the workspace may, whoever created it.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Folder ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The updated folder.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such folder in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "labels_delete_folder",
"summary": "Delete folder",
"description": "Removes the folder and unfiles everything it was attached to. The records themselves are kept.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Folder ID."
}
],
"responses": {
"204": {
"description": "Deleted."
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such folder in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/folders/{id}/move": {
"patch": {
"operationId": "labels_move_folder",
"summary": "Move folder",
"description": "Reorders the registry by placing this folder at `position`. Returns the full new ordering.",
"tags": [
"campaigns"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Folder ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MoveLabel"
}
}
}
},
"responses": {
"200": {
"description": "Every folder with its new position.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LabelOrder"
}
}
}
}
},
"400": {
"description": "Position out of range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such folder in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tags": {
"post": {
"operationId": "labels_create_tag",
"summary": "Create tag",
"description": "Mailbox tags. The new entry lands at the end of the workspace's registry. A registry holds at most 100 entries.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The created tag.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour, or the registry is full.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tags/{id}": {
"patch": {
"operationId": "labels_update_tag",
"summary": "Update tag",
"description": "Rename or recolour a tag. Any member of the workspace may, whoever created it.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Tag ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The updated tag.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such tag in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "labels_delete_tag",
"summary": "Delete tag",
"description": "Removes the tag and unfiles everything it was attached to. The records themselves are kept.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Tag ID."
}
],
"responses": {
"204": {
"description": "Deleted."
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such tag in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/tags/{id}/move": {
"patch": {
"operationId": "labels_move_tag",
"summary": "Move tag",
"description": "Reorders the registry by placing this tag at `position`. Returns the full new ordering.",
"tags": [
"mailboxes"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Tag ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MoveLabel"
}
}
}
},
"responses": {
"200": {
"description": "Every tag with its new position.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LabelOrder"
}
}
}
}
},
"400": {
"description": "Position out of range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such tag in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/categories": {
"post": {
"operationId": "labels_create_category",
"summary": "Create category",
"description": "Contact categories, which double as unified-inbox conversation labels. The new entry lands at the end of the workspace's registry. A registry holds at most 100 entries.",
"tags": [
"contacts"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The created category.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour, or the registry is full.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/categories/{id}": {
"patch": {
"operationId": "labels_update_category",
"summary": "Update category",
"description": "Rename or recolour a category. Any member of the workspace may, whoever created it.",
"tags": [
"contacts"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Category ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateLabel"
}
}
}
},
"responses": {
"200": {
"description": "The updated category.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Label"
}
}
}
},
"400": {
"description": "Invalid title or colour.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such category in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
},
"delete": {
"operationId": "labels_delete_category",
"summary": "Delete category",
"description": "Removes the category and unfiles everything it was attached to. The records themselves are kept.",
"tags": [
"contacts"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Category ID."
}
],
"responses": {
"204": {
"description": "Deleted."
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such category in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
},
"/categories/{id}/move": {
"patch": {
"operationId": "labels_move_category",
"summary": "Move category",
"description": "Reorders the registry by placing this category at `position`. Returns the full new ordering.",
"tags": [
"contacts"
],
"security": [
{
"bearerAuth": []
}
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
},
"description": "Category ID."
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MoveLabel"
}
}
}
},
"responses": {
"200": {
"description": "Every category with its new position.",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LabelOrder"
}
}
}
}
},
"400": {
"description": "Position out of range.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"401": {
"description": "Missing or invalid credentials.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Missing required scope or permission.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "No such category in this workspace.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Rate limited.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"description": "A Warmbly API key (wmbly_...) sent as a Bearer token."
}
},
"parameters": {
"IdempotencyKey": {
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "Optional client-generated key (1-255 chars). A retried request with the same key, method, path, and body replays the original response instead of acting twice.",
"schema": {
"type": "string",
"maxLength": 255
}
}
},
"schemas": {
"Error": {
"type": "object",
"description": "Standard error envelope returned for every 4xx/5xx response.",
"required": [
"error",
"code"
],
"properties": {
"error": {
"type": "string",
"description": "Human-readable message. Do not branch on this."
},
"message": {
"type": "string",
"description": "Alias of error in some responses."
},
"code": {
"type": "string",
"description": "Stable machine-readable code, e.g. bad_request, unauthorized, forbidden, not_found, conflict, rate_limit_exceeded, internal_error."
},
"request_id": {
"type": "string",
"description": "Correlates the response with server logs. Also returned as the X-Request-Id header."
}
}
},
"Pagination": {
"type": "object",
"description": "Keyset pagination metadata. next_cursor is an opaque token (not a record id).",
"required": [
"has_more"
],
"properties": {
"total": {
"type": [
"integer",
"null"
],
"description": "Total matching rows when cheaply known, else null."
},
"next_cursor": {
"type": [
"string",
"null"
],
"description": "Opaque cursor for the next page, or null on the last page."
},
"has_more": {
"type": "boolean"
}
}
},
"AuthCredentials": {
"type": "object",
"description": "Email/password credentials with a Cloudflare Turnstile token. Used for login start and registration start.",
"required": [
"email",
"password"
],
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Account email address."
},
"password": {
"type": "string",
"format": "password",
"description": "Account password."
},
"turnstile": {
"type": "string",
"description": "Cloudflare Turnstile challenge token."
}
}
},
"ConfirmRequest": {
"type": "object",
"description": "Confirms an in-flight login or registration: the opaque session handle plus the emailed one-time code.",
"required": [
"session",
"code"
],
"properties": {
"session": {
"type": "string",
"description": "Opaque session handle from the matching start call."
},
"code": {
"type": "string",
"description": "One-time confirmation code emailed to the user."
},
"turnstile": {
"type": "string",
"description": "Cloudflare Turnstile challenge token."
}
}
},
"AuthSession": {
"type": "object",
"description": "Opaque session handle returned by login/register start; pass it to the matching confirm call.",
"required": [
"session"
],
"properties": {
"session": {
"type": "string",
"description": "Opaque session handle."
}
}
},
"TokenPair": {
"type": "object",
"description": "An access/refresh token pair with absolute expiry timestamps.",
"required": [
"access_token",
"access_token_expires_at",
"refresh_token",
"refresh_token_expires_at"
],
"properties": {
"access_token": {
"type": "string",
"description": "Bearer access token for authenticated session requests."
},
"access_token_expires_at": {
"type": "string",
"format": "date-time",
"description": "When the access token expires."
},
"refresh_token": {
"type": "string",
"description": "Refresh token used to obtain a new pair."
},
"refresh_token_expires_at": {
"type": "string",
"format": "date-time",
"description": "When the refresh token expires."
}
}
},
"LoginResult": {
"type": "object",
"description": "Result of /auth/login/confirm: either a full token pair (the TokenPair fields are present) or a 2FA challenge (two_fa_required=true with a pending_token). The two cases are mutually exclusive.",
"properties": {
"access_token": {
"type": "string",
"description": "Present only when 2FA is not required."
},
"access_token_expires_at": {
"type": "string",
"format": "date-time"
},
"refresh_token": {
"type": "string"
},
"refresh_token_expires_at": {
"type": "string",
"format": "date-time"
},
"two_fa_required": {
"type": "boolean",
"description": "True when a 2FA challenge must be completed via /auth/2fa/verify."
},
"pending_token": {
"type": "string",
"description": "Single-use pending token to pass to /auth/2fa/verify. Present only when two_fa_required is true."
},
"expires_in": {
"type": "integer",
"description": "Seconds until the pending token expires. Present only when two_fa_required is true."
}
}
},
"RefreshRequest": {
"type": "object",
"description": "Request body for /auth/refresh.",
"required": [
"refresh_token"
],
"properties": {
"refresh_token": {
"type": "string",
"description": "A valid, unexpired refresh token."
}
}
},
"ResetPasswordStartRequest": {
"type": "object",
"description": "Request body for /auth/reset-password.",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"format": "email",
"description": "Email of the account to reset."
},
"turnstile": {
"type": "string",
"description": "Cloudflare Turnstile challenge token."
}
}
},
"ResetPasswordConfirmRequest": {
"type": "object",
"description": "Request body for /auth/reset-password/confirm.",
"required": [
"session",
"password"
],
"properties": {
"session": {
"type": "string",
"description": "Opaque reset session handle."
},
"password": {
"type": "string",
"format": "password",
"description": "The new password."
},
"turnstile": {
"type": "string",
"description": "Cloudflare Turnstile challenge token."
}
}
},
"ChangePasswordRequest": {
"type": "object",
"description": "Request body for /auth/me/password.",
"required": [
"current_password",
"new_password"
],
"properties": {
"current_password": {
"type": "string",
"format": "password",
"description": "The user's current password."
},
"new_password": {
"type": "string",
"format": "password",
"description": "The new password."
}
}
},
"UpdateProfileRequest": {
"type": "object",
"description": "Editable profile fields for the authenticated user.",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
}
}
},
"TwoFAVerifyRequest": {
"type": "object",
"description": "Request body for /auth/2fa/verify.",
"required": [
"pending_token",
"code"
],
"properties": {
"pending_token": {
"type": "string",
"description": "Single-use pending token from the login result."
},
"code": {
"type": "string",
"description": "A current TOTP code or a recovery code."
}
}
},
"TwoFACodeRequest": {
"type": "object",
"description": "A single TOTP or recovery code. Used to confirm enrollment or disable 2FA.",
"properties": {
"code": {
"type": "string",
"description": "A current TOTP code or a recovery code."
}
}
},
"TwoFAStatus": {
"type": "object",
"description": "Whether 2FA is enabled for the user.",
"required": [
"enabled"
],
"properties": {
"enabled": {
"type": "boolean"
}
}
},
"TwoFAEnrollStart": {
"type": "object",
"description": "The TOTP secret and otpauth provisioning URI, returned once at enrollment start.",
"required": [
"secret",
"otpauth_uri"
],
"properties": {
"secret": {
"type": "string",
"description": "Base32 (no padding) TOTP secret."
},
"otpauth_uri": {
"type": "string",
"description": "otpauth://totp/... provisioning URI for authenticator apps."
}
}
},
"TwoFARecoveryCodes": {
"type": "object",
"description": "One-time recovery codes, returned once when 2FA is enabled.",
"required": [
"recovery_codes"
],
"properties": {
"recovery_codes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Single-use recovery codes."
}
}
},
"OkResponse": {
"type": "object",
"description": "Generic success acknowledgement.",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
}
}
},
"PasskeyLoginChallenge": {
"type": "object",
"description": "WebAuthn assertion options plus the opaque login session handle for /auth/passkey/login/finish. The publicKey options follow the WebAuthn PublicKeyCredentialRequestOptions shape.",
"properties": {
"session": {
"type": "string",
"description": "Opaque login session handle."
},
"publicKey": {
"type": "object",
"additionalProperties": true,
"description": "WebAuthn PublicKeyCredentialRequestOptions (passed to navigator.credentials.get)."
}
}
},
"PasskeyLoginFinishRequest": {
"type": "object",
"description": "Request body for /auth/passkey/login/finish.",
"required": [
"session",
"credential"
],
"properties": {
"session": {
"type": "string",
"description": "Opaque login session handle from begin."
},
"credential": {
"type": "object",
"additionalProperties": true,
"description": "The WebAuthn assertion (PublicKeyCredential JSON) from navigator.credentials.get."
}
}
},
"PasskeyRenameRequest": {
"type": "object",
"description": "Request body for renaming a passkey.",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"description": "New display name for the passkey."
}
}
},
"PasskeyCredential": {
"type": "object",
"description": "A registered passkey (WebAuthn credential).",
"required": [
"id",
"name",
"credential_id",
"transports",
"backup_state",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"description": "User-assigned display name."
},
"provider": {
"type": "string",
"description": "Originating provider, when known."
},
"credential_id": {
"type": "string",
"description": "The WebAuthn credential id."
},
"transports": {
"type": "array",
"items": {
"type": "string"
},
"description": "Supported authenticator transports (e.g. internal, usb, hybrid)."
},
"backup_state": {
"type": "boolean",
"description": "Whether the credential is backed up / multi-device."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"PasskeyCredentialList": {
"type": "array",
"description": "A plain array of registered passkeys (not a paginated wrapper).",
"items": {
"$ref": "#/components/schemas/PasskeyCredential"
}
},
"Session": {
"type": "object",
"description": "A customer-facing view of an authenticated session.",
"required": [
"id",
"current",
"auth_provider",
"created_at",
"last_active_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"current": {
"type": "boolean",
"description": "True if this is the session making the request."
},
"browser": {
"type": "string"
},
"os": {
"type": "string"
},
"location_city": {
"type": "string"
},
"location_region": {
"type": "string"
},
"location_country": {
"type": "string"
},
"country_code": {
"type": "string"
},
"auth_provider": {
"type": "string",
"description": "How this session authenticated: email, google, apple, or webauthn."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"last_active_at": {
"type": "string",
"format": "date-time"
}
}
},
"SessionList": {
"type": "array",
"description": "A plain array of active sessions (not a paginated wrapper); the current session is floated to the top.",
"items": {
"$ref": "#/components/schemas/Session"
}
},
"UserLabelGroup": {
"type": "object",
"description": "A per-user label group (folder, tag, or category).",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
}
},
"additionalProperties": true
},
"User": {
"type": "object",
"description": "The authenticated user profile returned by /auth/me.",
"required": [
"id",
"first_name",
"last_name",
"email",
"roles",
"is_admin",
"folders",
"tags",
"categories",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"roles": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Organization role ids assigned to the user."
},
"referral_source": {
"type": [
"string",
"null"
]
},
"onboarding_completed_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"max_organizations": {
"type": "integer"
},
"free_trial_used": {
"type": "boolean"
},
"admin_permissions": {
"type": "integer",
"description": "Raw platform-admin permission bitmask."
},
"is_admin": {
"type": "boolean",
"description": "True if the user has any platform-admin permission."
},
"deletion_scheduled_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"deletion_scheduled_for": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"folders": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserLabelGroup"
},
"description": "Per-user folders (always an array)."
},
"tags": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserLabelGroup"
},
"description": "Per-user tags (always an array)."
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UserLabelGroup"
},
"description": "Per-user categories (always an array)."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"Mailbox": {
"type": "object",
"description": "A connected sender mailbox (email account).",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"worker_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"email": {
"type": "string",
"description": "The mailbox address."
},
"name": {
"type": "string",
"description": "Display name on outgoing mail."
},
"signature_plain": {
"type": "string"
},
"signature_html": {
"type": "string"
},
"signature_sync": {
"type": "boolean"
},
"signature_code": {
"type": "boolean"
},
"provider": {
"type": "string",
"enum": [
"gmail",
"outlook",
"smtp_imap"
]
},
"status": {
"type": "string",
"enum": [
"active",
"inactive",
"revoked"
]
},
"last_synced_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_id": {
"type": "integer"
},
"campaign_limit": {
"type": "integer",
"description": "Daily cold-campaign cap for this mailbox."
},
"min_wait_time": {
"type": "integer",
"description": "Minimum seconds between sends."
},
"reply_to": {
"type": "string"
},
"save_to_sent": {
"type": "boolean",
"description": "SMTP/IMAP mailboxes only: file a copy of each sent message in the mailbox's Sent folder. Ignored for Gmail and Outlook, whose APIs file their own copy."
},
"tracking_domain": {
"type": "string"
},
"tracking_domain_verified": {
"type": "boolean"
},
"tracking_domain_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"warmup": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Warmup anchor timestamp; null when warmup has never been enabled."
},
"warmup_paused_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Non-null when warmup is enabled but paused."
},
"warmup_base": {
"type": "integer"
},
"warmup_max": {
"type": "integer"
},
"warmup_increase": {
"type": "integer"
},
"warmup_reply_rate": {
"type": "integer"
},
"warmup_tag": {
"type": "string"
},
"warmup_pool_type": {
"type": "string",
"enum": [
"free",
"premium"
]
},
"warmup_start_time": {
"type": "string",
"description": "Daily warmup window start, HH:MM."
},
"warmup_end_time": {
"type": "string",
"description": "Daily warmup window end, HH:MM."
},
"warmup_days": {
"type": "integer"
},
"timezone": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"email",
"provider",
"status",
"campaign_limit",
"min_wait_time",
"created_at",
"updated_at"
]
},
"MailboxList": {
"type": "object",
"description": "A page of mailboxes.",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Mailbox"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
},
"required": [
"data",
"pagination"
]
},
"MailboxUpdate": {
"type": "object",
"description": "Mailbox settings patch. All fields optional; only present fields are applied.",
"properties": {
"name": {
"type": "string",
"description": "Display name on outgoing mail."
},
"signature_plain": {
"type": "string"
},
"signature_html": {
"type": "string"
},
"signature_sync": {
"type": "boolean"
},
"signature_code": {
"type": "boolean",
"description": "Treat the HTML signature as raw code."
},
"status": {
"type": "string",
"enum": [
"active",
"inactive",
"revoked"
]
},
"campaign_limit": {
"type": "integer",
"description": "Daily cold-campaign cap (validated up to 100)."
},
"min_wait_time": {
"type": "integer",
"description": "Minimum seconds between sends."
},
"reply_to": {
"type": "string"
},
"save_to_sent": {
"type": "boolean",
"description": "SMTP/IMAP mailboxes only: file a copy of each sent message in the mailbox's Sent folder. Ignored for Gmail and Outlook, whose APIs file their own copy."
},
"warmup": {
"type": "boolean",
"description": "Enable or disable warmup."
},
"warmup_base": {
"type": "integer",
"description": "Warmup starting volume per day."
},
"warmup_max": {
"type": "integer",
"description": "Warmup daily ceiling."
},
"warmup_increase": {
"type": "integer",
"description": "Per-day warmup ramp increment."
},
"warmup_reply_rate": {
"type": "integer",
"description": "Percentage of warmup threads to reply to."
},
"warmup_tag": {
"type": "string"
},
"warmup_start_time": {
"type": "string",
"description": "Daily warmup window start, HH:MM."
},
"warmup_end_time": {
"type": "string",
"description": "Daily warmup window end, HH:MM."
},
"warmup_days": {
"type": "integer"
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tag ids assigned to the mailbox."
}
}
},
"MailboxTrackingDomain": {
"type": "object",
"description": "The resolved custom tracking-domain state for a mailbox.",
"properties": {
"tracking_domain": {
"type": "string"
},
"tracking_domain_verified": {
"type": "boolean"
},
"tracking_domain_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Null until the CNAME resolves to the tracking host."
}
},
"required": [
"tracking_domain",
"tracking_domain_verified"
]
},
"MailboxAuthCheck": {
"type": "object",
"description": "On-demand SPF/DKIM/DMARC check for the mailbox's sending domain.",
"properties": {
"domain": {
"type": "string"
},
"spf_found": {
"type": "boolean"
},
"spf_record": {
"type": "string",
"description": "Omitted when SPF is not found."
},
"dkim_found": {
"type": "boolean"
},
"dkim_selectors": {
"type": "array",
"items": {
"type": "string"
},
"description": "Omitted when DKIM is not found."
},
"dmarc_found": {
"type": "boolean"
},
"dmarc_policy": {
"type": "string",
"description": "Omitted when DMARC is not found."
},
"all_aligned": {
"type": "boolean"
},
"summary": {
"type": "string"
}
},
"required": [
"domain",
"spf_found",
"dkim_found",
"dmarc_found",
"all_aligned",
"summary"
]
},
"MailboxSyncPolicy": {
"type": "object",
"description": "The fair-use budget a mailbox syncs under, resolved from the instance settings when it was loaded onto a worker.",
"properties": {
"backfill_days": {
"type": "integer",
"description": "How far back the initial import reaches."
},
"backfill_messages": {
"type": "integer",
"description": "The most messages the initial import stores for this mailbox."
},
"daily_messages": {
"type": "integer",
"description": "New (live) messages stored per UTC day. Replies to the mailbox's own sends have a separate budget of the same size."
},
"org_daily_messages": {
"type": "integer",
"description": "New plus imported messages stored across the organization per UTC day."
}
},
"required": [
"backfill_days",
"backfill_messages",
"daily_messages",
"org_daily_messages"
]
},
"MailboxSyncState": {
"type": "object",
"description": "The worker's most recent report of the mailbox's sync.",
"properties": {
"backfill_status": {
"type": "string",
"enum": [
"pending",
"running",
"complete"
]
},
"backfill_synced": {
"type": "integer",
"description": "Messages the initial import has stored so far."
},
"backfill_since": {
"type": "string",
"format": "date-time",
"description": "The cutoff the import uses, fixed when it started."
},
"backfill_started_at": {
"type": "string",
"format": "date-time"
},
"backfill_completed_at": {
"type": "string",
"format": "date-time"
},
"throttled_until": {
"type": "string",
"format": "date-time",
"description": "Set while fair use is holding new mail; the hold ends at this time at the latest."
},
"throttle_reason": {
"type": "string",
"enum": [
"",
"burst",
"hourly",
"daily",
"org_daily",
"priority_daily"
],
"description": "Which budget is exhausted while throttled_until is set."
},
"deferred": {
"type": "integer",
"description": "New messages seen on the server that are waiting on budget."
},
"last_synced_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"backfill_status",
"backfill_synced",
"deferred"
]
},
"MailboxSync": {
"type": "object",
"properties": {
"state": {
"oneOf": [
{
"$ref": "#/components/schemas/MailboxSyncState"
},
{
"type": "null"
}
],
"description": "Null until the worker has reported once."
},
"policy": {
"$ref": "#/components/schemas/MailboxSyncPolicy"
}
},
"required": [
"state",
"policy"
]
},
"MailboxVerifyRequest": {
"type": "object",
"description": "Address to verify. Required if the email query param is not set.",
"properties": {
"email": {
"type": "string",
"description": "The address to verify."
}
}
},
"MailboxVerifyResult": {
"type": "object",
"description": "Result of a single-address verification.",
"properties": {
"email": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"valid",
"risky",
"invalid",
"unknown"
]
},
"reason": {
"type": "string"
},
"is_catch_all": {
"type": "boolean"
},
"has_mx": {
"type": "boolean"
},
"checked_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"email",
"status",
"reason",
"is_catch_all",
"has_mx",
"checked_at"
]
},
"MailboxWarmupBanStatus": {
"type": "object",
"description": "Whether a mailbox is blocked from the shared warmup pool.",
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid"
},
"blocked": {
"type": "boolean"
},
"health_state": {
"type": "string",
"description": "Rolling warmup health.",
"enum": [
"healthy",
"watch",
"throttled",
"quarantined",
"blocked"
]
},
"reason": {
"type": "string",
"description": "Omitted when not blocked."
},
"blocked_at": {
"type": "string",
"format": "date-time",
"description": "Omitted when not blocked."
},
"blocked_until": {
"type": "string",
"format": "date-time",
"description": "Omitted when not blocked."
},
"can_appeal": {
"type": "boolean"
},
"pending_appeal": {
"type": "boolean"
}
},
"required": [
"email_account_id",
"blocked",
"health_state",
"can_appeal",
"pending_appeal"
]
},
"MailboxWarmupAppealRequest": {
"type": "object",
"description": "A warmup-ban appeal.",
"properties": {
"reason": {
"type": "string",
"description": "The owner's explanation for the appeal."
}
}
},
"MailboxWarmupAppealResult": {
"type": "object",
"properties": {
"appeal_id": {
"type": "string",
"format": "uuid"
}
},
"required": [
"appeal_id"
]
},
"MailboxSendRequest": {
"type": "object",
"description": "A one-off send from a specific mailbox.",
"properties": {
"to": {
"type": "array",
"items": {
"type": "string"
},
"description": "Recipient addresses."
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"in_reply_to": {
"type": "array",
"items": {
"type": "string"
},
"description": "Message ids this email replies to."
},
"thread_id": {
"type": "string",
"description": "Thread id to attach the message to."
},
"send_mode": {
"type": "string",
"enum": [
"instant",
"smart",
"scheduled"
],
"default": "instant",
"description": "instant (default), smart (next per-mailbox scheduler gap), or scheduled (use scheduled_at)."
},
"scheduled_at": {
"type": "string",
"format": "date-time",
"description": "Required when send_mode is scheduled. Must be in the future."
}
},
"required": [
"to",
"subject"
]
},
"MailboxSendResult": {
"type": "object",
"description": "The queued send task.",
"properties": {
"task_id": {
"type": "string",
"format": "uuid",
"description": "Identifies the queued send task."
},
"scheduled_at": {
"type": "string",
"format": "date-time",
"description": "Resolved dispatch time."
},
"send_mode": {
"type": "string",
"enum": [
"instant",
"smart",
"scheduled"
]
}
},
"required": [
"task_id",
"scheduled_at",
"send_mode"
]
},
"CampaignStatus": {
"type": "string",
"description": "Campaign lifecycle status.",
"enum": [
"draft",
"scheduled",
"active",
"paused",
"paused_no_accounts",
"completed",
"stopped"
]
},
"ScheduleWindows": {
"type": "array",
"description": "Per-day sending schedule. 7-element array indexed by time.Weekday (Sunday = 0); each day is a list of {start, end} minute intervals. When non-empty it supersedes days/start_time/end_time.",
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"start": {
"type": "integer",
"description": "Minutes from midnight."
},
"end": {
"type": "integer",
"description": "Minutes from midnight."
}
}
}
}
},
"Campaign": {
"type": "object",
"required": [
"id",
"name",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"description": "Creator user id."
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/CampaignStatus"
},
"stop_on_reply": {
"type": "boolean"
},
"open_tracking": {
"type": "boolean"
},
"link_tracking": {
"type": "boolean"
},
"text_only": {
"type": "boolean"
},
"daily_limit": {
"type": "integer"
},
"unsubscribe_header": {
"type": "boolean"
},
"risky_emails": {
"type": "boolean"
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"start_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"end_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"timezone": {
"type": "string",
"description": "IANA timezone."
},
"days": {
"type": "integer",
"description": "Legacy weekday bitmask (0-127), superseded by schedule_windows."
},
"start_time": {
"type": "string",
"description": "Legacy daily start (HH:MM)."
},
"end_time": {
"type": "string",
"description": "Legacy daily end (HH:MM)."
},
"schedule_windows": {
"$ref": "#/components/schemas/ScheduleWindows"
},
"email_tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Mailbox tag ids resolving the sender pool (tags strategy)."
},
"folders": {
"type": "array",
"items": {
"type": "string"
}
},
"contact_order_by": {
"type": "string"
},
"contact_order_dir": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"contact_order_field": {
"type": [
"string",
"null"
]
},
"sender_strategy": {
"type": "string",
"description": "How the campaign resolves its sending mailboxes. \"tags\" reads email_tags and falls back to every active mailbox in the workspace when no tag and no explicit sender is set. \"explicit\" sends from the campaign_senders pool and any email_tags set alongside it, and never falls back to every active mailbox: an empty pool with no tags parks the campaign at paused_no_accounts instead of widening to the whole workspace.",
"enum": [
"tags",
"explicit"
]
},
"rotation_mode": {
"type": "string",
"description": "How volume spreads across mailboxes."
},
"ramp_enabled": {
"type": "boolean"
},
"ramp_start": {
"type": "integer"
},
"ramp_increment": {
"type": "integer"
},
"ramp_ceiling": {
"type": "integer"
},
"ramp_level": {
"type": "integer",
"description": "Server-managed current ramp level."
},
"esp_match_mode": {
"type": "string",
"enum": [
"off",
"prefer",
"strict"
]
},
"max_new_leads_per_day": {
"type": "integer",
"description": "0 = unlimited."
},
"prioritize_new_leads": {
"type": "boolean"
},
"tracking_domain": {
"type": "string"
},
"tracking_domain_verified": {
"type": "boolean"
},
"tracking_domain_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_status_change_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Campaign"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"CampaignCreate": {
"type": "object",
"required": [
"name"
],
"description": "Only name is required; every other field is optional and applied only when sent.",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"stop_on_reply": {
"type": "boolean"
},
"open_tracking": {
"type": "boolean"
},
"link_tracking": {
"type": "boolean"
},
"text_only": {
"type": "boolean"
},
"daily_limit": {
"type": "integer"
},
"unsubscribe_header": {
"type": "boolean"
},
"risky_emails": {
"type": "boolean"
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"start_date": {
"type": "string",
"format": "date-time"
},
"end_date": {
"type": "string",
"format": "date-time"
},
"timezone": {
"type": "string"
},
"days": {
"type": "integer",
"description": "Legacy weekday bitmask (0-127), superseded by schedule_windows."
},
"start_time": {
"type": "string",
"description": "Legacy daily start (HH:MM)."
},
"end_time": {
"type": "string",
"description": "Legacy daily end (HH:MM)."
},
"schedule_windows": {
"$ref": "#/components/schemas/ScheduleWindows"
},
"email_tag_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Mailbox tag ids that resolve the sender pool (tags strategy)."
},
"folder_ids": {
"type": "array",
"items": {
"type": "string"
}
},
"sender_strategy": {
"type": "string",
"description": "How the campaign resolves its sending mailboxes. \"tags\" reads email_tag_ids and falls back to every active mailbox in the workspace when no tag and no explicit sender is set. \"explicit\" sends from the campaign_senders pool and any email_tag_ids set alongside it, and never falls back to every active mailbox: an empty pool with no tags parks the campaign at paused_no_accounts instead of widening to the whole workspace.",
"enum": [
"tags",
"explicit"
]
},
"rotation_mode": {
"type": "string"
},
"senders": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignSenderInput"
},
"description": "Explicit-strategy mailbox pool."
},
"ramp_enabled": {
"type": "boolean"
},
"ramp_start": {
"type": "integer"
},
"ramp_increment": {
"type": "integer"
},
"ramp_ceiling": {
"type": "integer"
},
"esp_match_mode": {
"type": "string",
"enum": [
"off",
"prefer",
"strict"
]
},
"max_new_leads_per_day": {
"type": "integer",
"description": "0 = unlimited."
},
"prioritize_new_leads": {
"type": "boolean"
},
"tracking_domain": {
"type": "string"
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignStepCreate"
},
"description": "Initial sequence steps in order. They are connected in order: each step routes unconditionally to the next, waiting that step's wait_after days (first step 0, follow-ups 3 unless given)."
},
"variants": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignABVariantCreate"
},
"description": "A/B variants for the first step."
},
"advanced_overrides": {
"$ref": "#/components/schemas/AdvancedOutreachSettings"
}
}
},
"CampaignUpdate": {
"type": "object",
"description": "Every field optional; any field sent is applied, omitted fields unchanged.",
"properties": {
"name": {
"type": "string"
},
"description": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/CampaignStatus"
},
"stop_on_reply": {
"type": "boolean"
},
"open_tracking": {
"type": "boolean"
},
"link_tracking": {
"type": "boolean"
},
"text_only": {
"type": "boolean"
},
"daily_limit": {
"type": "integer"
},
"unsubscribe_header": {
"type": "boolean"
},
"risky_emails": {
"type": "boolean"
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"start_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"end_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"timezone": {
"type": "string"
},
"days": {
"type": "integer"
},
"start_time": {
"type": "string"
},
"end_time": {
"type": "string"
},
"schedule_windows": {
"$ref": "#/components/schemas/ScheduleWindows"
},
"email_tags": {
"type": "array",
"items": {
"type": "string"
}
},
"folders": {
"type": "array",
"items": {
"type": "string"
}
},
"contact_order_by": {
"type": "string"
},
"contact_order_dir": {
"type": "string",
"enum": [
"asc",
"desc"
]
},
"contact_order_field": {
"type": "string"
},
"sender_strategy": {
"type": "string",
"description": "How the campaign resolves its sending mailboxes. \"tags\" reads email_tags and falls back to every active mailbox in the workspace when no tag and no explicit sender is set. \"explicit\" sends from the campaign_senders pool and any email_tags set alongside it, and never falls back to every active mailbox: an empty pool with no tags parks the campaign at paused_no_accounts instead of widening to the whole workspace.",
"enum": [
"tags",
"explicit"
]
},
"rotation_mode": {
"type": "string"
},
"ramp_enabled": {
"type": "boolean"
},
"ramp_start": {
"type": "integer"
},
"ramp_increment": {
"type": "integer"
},
"ramp_ceiling": {
"type": "integer"
},
"esp_match_mode": {
"type": "string",
"enum": [
"off",
"prefer",
"strict"
]
},
"max_new_leads_per_day": {
"type": "integer"
},
"prioritize_new_leads": {
"type": "boolean"
},
"tracking_domain": {
"type": "string"
}
}
},
"CampaignSender": {
"type": "object",
"required": [
"email_account_id",
"weight",
"enabled"
],
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid"
},
"weight": {
"type": "integer"
},
"last_sent_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"enabled": {
"type": "boolean"
}
}
},
"CampaignSenderInput": {
"type": "object",
"required": [
"email_account_id"
],
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid"
},
"weight": {
"type": "integer"
},
"enabled": {
"type": "boolean"
}
}
},
"CampaignSenderList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignSender"
}
}
}
},
"CampaignSendersReplace": {
"type": "object",
"required": [
"senders"
],
"properties": {
"senders": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignSenderInput"
},
"description": "The full new sender pool."
}
}
},
"CampaignStep": {
"type": "object",
"description": "A sequence step (email or action/condition node).",
"required": [
"id",
"kind",
"position",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_sync": {
"type": "boolean",
"description": "Keep plain and HTML bodies in sync."
},
"body_code": {
"type": "boolean",
"description": "Treat the body as raw code."
},
"wait_after": {
"type": "integer",
"description": "Days to wait before this step, counted from the contact's previous step."
},
"position": {
"type": "integer"
},
"kind": {
"type": "string",
"enum": [
"email",
"action",
"wait"
]
},
"conditions": {
"type": "object",
"description": "The connections out of this step ({branches: [...]}). Empty means no outgoing path: the flow ends here for the contact.",
"additionalProperties": true
},
"action": {
"type": "object",
"description": "Typed config for non-email nodes.",
"additionalProperties": true
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignStepCreate": {
"type": "object",
"description": "Initial step shape used inside campaign create (sequences[]).",
"properties": {
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"body_html": {
"type": "string"
},
"wait_after": {
"type": "integer"
},
"kind": {
"type": "string",
"enum": [
"email",
"action",
"wait"
]
}
}
},
"CampaignStepUpdate": {
"type": "object",
"description": "Patch a step. All fields optional.",
"properties": {
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_sync": {
"type": "boolean"
},
"body_code": {
"type": "boolean"
},
"wait_after": {
"type": "integer",
"description": "Days to wait before this step, counted from the contact's previous step (0 to 60). Spacing belongs to the target step; there is no standalone wait node for email steps."
},
"conditions": {
"type": "object",
"description": "The connections out of this step ({branches: [...]}), evaluated in order; a branch with no conditions is a plain go-there-next link. Routing follows connections only: {} or empty branches means no outgoing path, which ends the flow for the contact.",
"additionalProperties": true
},
"kind": {
"type": "string",
"enum": [
"email",
"action",
"wait"
]
},
"action": {
"type": "object",
"description": "Typed config for non-email nodes; type is the switch (wait, add_tag, remove_tag, unsubscribe, notify, create_task, create_deal, move_deal_stage, run_automation, end).",
"additionalProperties": true
}
}
},
"CampaignABVariant": {
"type": "object",
"required": [
"id",
"campaign_id",
"name",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"step_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Step the variant is scoped to; null is campaign-level."
},
"name": {
"type": "string"
},
"weight": {
"type": "integer"
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"is_control": {
"type": "boolean"
},
"is_active": {
"type": "boolean"
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignABVariantList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignABVariant"
}
}
}
},
"CampaignABVariantCreate": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string"
},
"step_id": {
"type": "string",
"format": "uuid",
"description": "Step to scope the variant to; omit for campaign-level."
},
"weight": {
"type": "integer"
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"is_control": {
"type": "boolean"
},
"is_active": {
"type": "boolean"
},
"metadata": {
"type": "object",
"additionalProperties": true
}
}
},
"CampaignABVariantUpdate": {
"type": "object",
"description": "Patch a variant. All fields optional.",
"properties": {
"name": {
"type": "string"
},
"weight": {
"type": "integer"
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"is_control": {
"type": "boolean"
},
"is_active": {
"type": "boolean"
},
"metadata": {
"type": "object",
"additionalProperties": true
}
}
},
"ABWinnerAnalysis": {
"type": "object",
"required": [
"campaign_id",
"variants"
],
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"variants": {
"type": "array",
"items": {
"type": "object",
"properties": {
"variant_id": {
"type": "string",
"format": "uuid"
},
"variant_name": {
"type": "string"
},
"total_sent": {
"type": "integer"
},
"opened": {
"type": "integer"
},
"clicked": {
"type": "integer"
},
"replied": {
"type": "integer"
},
"bounced": {
"type": "integer"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"bounce_rate": {
"type": "number"
}
}
}
},
"winner_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"winner_name": {
"type": [
"string",
"null"
]
},
"winning_rule": {
"type": "string"
},
"confidence": {
"type": "string",
"description": "Winner confidence (e.g. low, medium, high)."
}
}
},
"CampaignAttachment": {
"type": "object",
"required": [
"id",
"campaign_id",
"step_id",
"filename",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"step_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "The sequence step that sends this file. Null means every step of the campaign sends it."
},
"filename": {
"type": "string"
},
"size": {
"type": "integer",
"description": "Size in bytes."
},
"mime_type": {
"type": "string"
},
"url": {
"type": "string",
"description": "Short-lived presigned download URL."
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignAttachmentList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignAttachment"
}
}
}
},
"CampaignLog": {
"type": "object",
"required": [
"id",
"campaign_id",
"event_type",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"event_type": {
"type": "string",
"description": "e.g. campaign_started."
},
"message": {
"type": "string"
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignLogList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignLog"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"CampaignAdvancedSettings": {
"type": "object",
"required": [
"campaign_id",
"overrides"
],
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"overrides": {
"$ref": "#/components/schemas/AdvancedOutreachSettings"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignAdvancedUpdate": {
"type": "object",
"required": [
"settings"
],
"properties": {
"settings": {
"$ref": "#/components/schemas/AdvancedOutreachSettings"
}
}
},
"AdvancedOutreachSettings": {
"type": "object",
"description": "Advanced outreach overrides for a campaign.",
"properties": {
"bounce_pipeline": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"auto_suppress_on_bounce": {
"type": "boolean"
},
"auto_suppress_on_complaint": {
"type": "boolean"
},
"auto_suppress_on_unsubscribe": {
"type": "boolean"
},
"auto_pause_campaign_on_spike": {
"type": "boolean"
},
"pause_bounce_rate_threshold": {
"type": "number"
},
"pause_complaint_rate_threshold": {
"type": "number"
}
}
},
"task_reliability": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"dlq_enabled": {
"type": "boolean"
},
"max_attempts": {
"type": "integer"
},
"execution_window_seconds": {
"type": "integer"
}
}
},
"ab_testing": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"default_winning_rule": {
"type": "string"
},
"auto_promote_winner": {
"type": "boolean"
},
"min_sample_size": {
"type": "integer"
}
}
},
"reply_intent": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"positive_keywords": {
"type": "array",
"items": {
"type": "string"
}
},
"negative_keywords": {
"type": "array",
"items": {
"type": "string"
}
},
"out_of_office_keywords": {
"type": "array",
"items": {
"type": "string"
}
},
"question_keywords": {
"type": "array",
"items": {
"type": "string"
}
},
"auto_create_crm_task": {
"type": "boolean"
},
"auto_pause_on_negative": {
"type": "boolean"
},
"auto_suppress_on_unsubscribe_keyword": {
"type": "boolean"
}
}
},
"send_time_optimization": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"use_contact_timezone": {
"type": "boolean"
},
"default_contact_timezone": {
"type": "string"
},
"preferred_hours": {
"type": "array",
"items": {
"type": "integer"
}
},
"weekend_weight_multiplier": {
"type": "number"
}
}
},
"preflight": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"check_tracking_domain": {
"type": "boolean"
},
"check_unsubscribe_header": {
"type": "boolean"
},
"check_ab_variant_configured": {
"type": "boolean"
},
"check_daily_limit": {
"type": "boolean"
},
"check_schedule_window": {
"type": "boolean"
}
}
},
"dashboard": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"show_suppression_log": {
"type": "boolean"
},
"show_intent_summary": {
"type": "boolean"
},
"show_dlq_stats": {
"type": "boolean"
}
}
},
"unsubscribe": {
"type": "object",
"description": "Workspace default for the opt-out appended after the signature of every campaign email; a campaign's unsubscribe_mode overrides it.",
"properties": {
"mode": {
"type": "string",
"enum": [
"text",
"link",
"off"
]
},
"text": {
"type": "string",
"maxLength": 300
},
"link_intro": {
"type": "string",
"maxLength": 300
},
"link_text": {
"type": "string",
"maxLength": 300
}
}
}
}
},
"PreflightReport": {
"type": "object",
"required": [
"campaign_id",
"passed",
"score",
"checks"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"passed": {
"type": "boolean"
},
"score": {
"type": "integer"
},
"checks": {
"type": "array",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"passed": {
"type": "boolean"
},
"severity": {
"type": "string",
"description": "e.g. warning, error."
},
"message": {
"type": "string"
},
"remediation": {
"type": "string"
}
}
}
},
"recommendations": {
"type": "array",
"items": {
"type": "string"
}
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignTestEmailRequest": {
"type": "object",
"required": [
"account_id",
"recipient"
],
"properties": {
"account_id": {
"type": "string",
"format": "uuid",
"description": "Sending mailbox id."
},
"recipient": {
"type": "string",
"format": "email",
"description": "Where to send the test."
},
"step_id": {
"type": "string",
"format": "uuid",
"description": "Step to render and send; defaults to the first step."
}
}
},
"CampaignTestEmailResult": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"recipient": {
"type": "string",
"format": "email"
},
"subject": {
"type": "string"
},
"account_id": {
"type": "string",
"format": "uuid"
}
}
},
"CampaignStartResult": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "started"
}
}
},
"CampaignStopResult": {
"type": "object",
"properties": {
"status": {
"type": "string",
"example": "stopped"
}
}
},
"TrackingDomainStatus": {
"type": "object",
"properties": {
"tracking_domain": {
"type": "string"
},
"tracking_domain_verified": {
"type": "boolean"
},
"tracking_domain_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"TemplatePreviewRequest": {
"type": "object",
"properties": {
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "A contact of the organization to render for. Omitted renders the built-in sample. Requires READ_CONTACTS."
},
"campaign_id": {
"type": "string",
"format": "uuid",
"description": "Campaign whose opt-out footer, plain-text setting and attachments apply."
},
"account_id": {
"type": "string",
"format": "uuid",
"description": "Mailbox whose signature applies and which is reported as the sender."
},
"step_id": {
"type": "string",
"format": "uuid",
"description": "The step being previewed, so the attachment list is the one that step sends. Omitted lists the campaign-wide files only."
},
"contact": {
"type": "object",
"description": "Override fields on the built-in sample contact.",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"company": {
"type": "string"
},
"phone": {
"type": "string"
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
},
"TemplatePreview": {
"type": "object",
"properties": {
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"errors": {
"type": "array",
"items": {
"type": "string"
},
"description": "Template parse errors that would block sending. Omitted when empty."
},
"unresolved": {
"type": "array",
"items": {
"type": "string"
},
"description": "Literal {{...}} tokens left after render. Omitted when empty."
},
"from": {
"type": "object",
"description": "The sender as recipients see it. Present when account_id was given.",
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
}
}
},
"attachments": {
"type": "array",
"description": "The files this send carries: the campaign-wide attachments plus step_id's own. Present when campaign_id was given and there are any.",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"filename": {
"type": "string"
},
"size": {
"type": "integer",
"description": "Size in bytes."
},
"mime_type": {
"type": "string"
}
}
}
}
}
},
"GenerationWriteRequest": {
"type": "object",
"required": [
"prompt"
],
"properties": {
"prompt": {
"type": "string",
"maxLength": 8000,
"description": "The instruction to generate from."
},
"tone": {
"type": "string",
"description": "Desired tone (e.g. friendly, direct)."
}
}
},
"GenerationWriteResult": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"credits_remaining": {
"type": "integer"
},
"model": {
"type": "string"
}
}
},
"MiniCategory": {
"type": "object",
"description": "Denormalised category chip attached to a contact.",
"required": [
"id",
"title",
"color"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string"
},
"color": {
"type": "string",
"description": "Hex color, e.g. #0ea5e9."
}
}
},
"MiniCampaign": {
"type": "object",
"description": "Denormalised campaign reference attached to a contact.",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"ContactCampaignProgress": {
"type": "object",
"description": "A contact's aggregate processing state inside one campaign. Present on search results only when filtering by exactly one campaign.",
"required": [
"status",
"sent",
"opened",
"clicked",
"replied",
"bounced"
],
"properties": {
"status": {
"type": "string",
"enum": [
"pending",
"active",
"completed",
"replied",
"bounced",
"failed",
"unsubscribed"
],
"description": "Derived, highest priority first: unsubscribed, bounced, replied, failed (a step could not be sent after every retry), completed (every email step sent), active (some steps sent), pending (nothing sent yet)."
},
"sent": {
"type": "integer"
},
"opened": {
"type": "integer"
},
"clicked": {
"type": "integer"
},
"replied": {
"type": "integer"
},
"bounced": {
"type": "integer"
},
"current_step": {
"type": "string",
"description": "Label of the step the contact is on now. Empty when nothing sent yet."
},
"failure_reason": {
"type": "string",
"description": "Why the last send failed, as reported by the sending worker. Present only when status is failed."
},
"last_activity_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"Contact": {
"type": "object",
"description": "A contact record.",
"required": [
"id",
"first_name",
"last_name",
"email",
"company",
"phone",
"custom_fields",
"subscribed",
"campaigns",
"categories",
"verification_status",
"verification_reason",
"is_catch_all",
"esp_provider",
"updated_at",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"company": {
"type": "string"
},
"phone": {
"type": "string"
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Arbitrary string key/value custom fields."
},
"subscribed": {
"type": "boolean"
},
"campaigns": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MiniCampaign"
}
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MiniCategory"
}
},
"verification_status": {
"type": "string",
"enum": [
"valid",
"risky",
"invalid",
"unknown"
],
"description": "Pre-send verification state."
},
"verification_reason": {
"type": "string"
},
"is_catch_all": {
"type": "boolean"
},
"verification_checked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"esp_provider": {
"type": "string",
"description": "Recipient ESP derived from the domain: '' | gmail | outlook | other."
},
"esp_resolved_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"campaign_lead": {
"allOf": [
{
"$ref": "#/components/schemas/ContactCampaignProgress"
}
],
"description": "Present only when search filters by exactly one campaign."
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"ContactList": {
"type": "object",
"description": "A page of contacts.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Contact"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"ContactEngagement": {
"type": "object",
"description": "Aggregate email engagement summary for a single contact.",
"required": [
"total_sent",
"total_opened",
"total_clicked",
"total_replied",
"total_bounced",
"total_complained"
],
"properties": {
"total_sent": {
"type": "integer"
},
"total_opened": {
"type": "integer"
},
"total_clicked": {
"type": "integer"
},
"total_replied": {
"type": "integer"
},
"total_bounced": {
"type": "integer"
},
"total_complained": {
"type": "integer"
},
"last_sent_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_opened_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_clicked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_replied_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_bounced_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"ContactSuppression": {
"type": "object",
"description": "Suppression state for the contact's email. Null when not suppressed.",
"required": [
"reason",
"source",
"created_at"
],
"properties": {
"reason": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"bounce",
"complaint",
"unsubscribe"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"ContactDetail": {
"description": "The hydrated contact 360 payload: the contact plus engagement and suppression.",
"allOf": [
{
"$ref": "#/components/schemas/Contact"
},
{
"type": "object",
"required": [
"engagement"
],
"properties": {
"engagement": {
"$ref": "#/components/schemas/ContactEngagement"
},
"suppression": {
"allOf": [
{
"$ref": "#/components/schemas/ContactSuppression"
}
]
}
}
}
]
},
"ContactSearchRequest": {
"type": "object",
"description": "Faceted contact search filters. All fields optional.",
"properties": {
"query": {
"type": "string",
"description": "Text search across name, email, company."
},
"custom_field_filters": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactCustomFieldFilter"
}
},
"campaign_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Contact must be in ALL of these campaigns."
},
"category_ids": {
"type": "array",
"items": {
"type": "string"
},
"description": "Contact must have ALL of these categories."
},
"min_campaigns": {
"type": "integer",
"description": "Minimum number of associated campaigns."
},
"max_campaigns": {
"type": "integer",
"description": "Maximum number of associated campaigns."
},
"subscribed": {
"type": "boolean"
},
"created_after": {
"type": "string",
"format": "date-time"
},
"created_before": {
"type": "string",
"format": "date-time"
},
"updated_after": {
"type": "string",
"format": "date-time"
},
"updated_before": {
"type": "string",
"format": "date-time"
},
"sort_by": {
"type": "string",
"description": "Sort column: created_at (the default), updated_at, first_name, last_name, email, or campaign_count. Any other value falls back to created_at."
},
"reverse": {
"type": "boolean",
"description": "Ascending when true. The default is descending."
}
}
},
"ContactCustomFieldFilter": {
"type": "object",
"description": "A single custom-field filter clause.",
"required": [
"name",
"value",
"type"
],
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"equal",
"starts_with",
"ends_with",
"contains"
]
}
}
},
"ContactCreate": {
"type": "object",
"description": "A contact to create.",
"required": [
"email"
],
"properties": {
"email": {
"type": "string",
"format": "email"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"company": {
"type": "string"
},
"phone": {
"type": "string"
},
"campaigns": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Campaign IDs to add the contact to."
},
"categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Category IDs to assign."
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
},
"ContactUpdate": {
"type": "object",
"description": "Partial update for a single contact. Only present fields change.",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"company": {
"type": "string"
},
"phone": {
"type": "string"
},
"custom_fields": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Replaces the custom-fields map."
},
"subscribed": {
"type": "boolean"
},
"campaigns": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Set the full campaign membership (omit to leave as-is)."
},
"categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Set the full category list (omit to leave as-is)."
},
"add_categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Diff-style add (ignored when categories is set)."
},
"remove_categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Diff-style remove (ignored when categories is set)."
}
}
},
"ContactSelection": {
"type": "object",
"description": "Names the contacts a bulk action applies to: either an explicit id list, or every contact matching a search (all + filters) minus the ids in exclude. The filter form lets one call cover far more contacts than a page, and is refused with selection_too_large past 50000 matches.",
"oneOf": [
{
"required": [
"contacts"
],
"properties": {
"all": {
"enum": [
false
]
}
}
},
{
"required": [
"all",
"filters"
],
"properties": {
"all": {
"enum": [
true
]
}
}
}
],
"properties": {
"contacts": {
"type": "array",
"minItems": 1,
"maxItems": 1000,
"items": {
"type": "string",
"format": "uuid"
},
"description": "Contact ids (1 to 1000). Required unless all is set."
},
"all": {
"type": "boolean",
"description": "Resolve the selection from filters instead of contacts."
},
"filters": {
"allOf": [
{
"$ref": "#/components/schemas/ContactSearchRequest"
}
],
"description": "The search whose matches the action applies to. Required when all is true."
},
"exclude": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"maxItems": 50000,
"description": "Contact ids to drop from the resolved set. Ignored unless all is set."
}
}
},
"ContactBulkUpdateRequest": {
"type": "object",
"description": "One set of edits applied across a selection of contacts.",
"oneOf": [
{
"required": [
"contacts"
],
"properties": {
"all": {
"enum": [
false
]
}
}
},
{
"required": [
"all",
"filters"
],
"properties": {
"all": {
"enum": [
true
]
}
}
}
],
"properties": {
"contacts": {
"type": "array",
"minItems": 1,
"maxItems": 1000,
"items": {
"type": "string",
"format": "uuid"
},
"description": "Contact IDs to edit (1 to 1000). Required unless all is set."
},
"all": {
"type": "boolean",
"description": "Resolve the selection from filters instead of contacts."
},
"filters": {
"allOf": [
{
"$ref": "#/components/schemas/ContactSearchRequest"
}
],
"description": "The search whose matches the action applies to. Required when all is true."
},
"exclude": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"maxItems": 50000,
"description": "Contact ids to drop from the resolved set. Ignored unless all is set."
},
"add_campaigns": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"remove_campaigns": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"add_categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"remove_categories": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"fields": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactBulkFieldOp"
}
},
"subscribe": {
"type": "boolean",
"description": "Set subscription status for all listed contacts."
}
}
},
"ContactBulkFieldOp": {
"type": "object",
"description": "A custom-field operation applied during a bulk update.",
"required": [
"type",
"key"
],
"properties": {
"type": {
"type": "string",
"enum": [
"ADD",
"EDIT",
"DELETE",
"RENAME"
]
},
"key": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"ContactExportRequest": {
"type": "object",
"description": "Body for a contact export.",
"required": [
"format",
"scope"
],
"properties": {
"format": {
"type": "string",
"enum": [
"csv",
"xlsx",
"json"
]
},
"scope": {
"type": "string",
"enum": [
"all",
"filtered",
"selected"
]
},
"contact_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Contact IDs when scope is selected."
},
"filters": {
"allOf": [
{
"$ref": "#/components/schemas/ContactSearchRequest"
}
],
"description": "A search filter body when scope is filtered."
},
"fields": {
"type": "array",
"items": {
"type": "string"
},
"description": "Column identifiers in display order (built-ins like email, first_name, or custom:<key>). Empty uses defaults."
},
"filename": {
"type": "string",
"description": "Filename without extension. Sanitized server-side; empty falls back to contacts-<YYYY-MM-DD>."
}
}
},
"ContactImportColumnMapping": {
"type": "object",
"description": "Maps a source column index to a target contact field.",
"required": [
"index",
"target"
],
"properties": {
"index": {
"type": "integer",
"description": "Zero-based source column index."
},
"target": {
"type": "string",
"enum": [
"ignore",
"email",
"first_name",
"last_name",
"company",
"phone",
"subscribed",
"categories"
],
"description": "Target field, or a custom:<key> string for a custom field."
},
"custom_key": {
"type": "string",
"description": "Custom-field key when target is custom:<key>."
}
}
},
"ContactImportPreview": {
"type": "object",
"description": "Detected columns and a sample for building a column mapping.",
"required": [
"filename",
"format",
"total_rows",
"columns",
"has_header",
"sample_rows",
"suggested_mapping"
],
"properties": {
"filename": {
"type": "string"
},
"format": {
"type": "string",
"description": "csv or xlsx."
},
"total_rows": {
"type": "integer"
},
"columns": {
"type": "array",
"items": {
"type": "string"
}
},
"has_header": {
"type": "boolean"
},
"sample_rows": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "Capped at 20 rows."
},
"suggested_mapping": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactImportColumnMapping"
}
}
}
},
"ContactImportRowError": {
"type": "object",
"description": "A single failed import row.",
"required": [
"line",
"reason"
],
"properties": {
"line": {
"type": "integer"
},
"email": {
"type": "string"
},
"values": {
"type": "array",
"items": {
"type": "string"
}
},
"reason": {
"type": "string"
}
}
},
"ContactImportResult": {
"type": "object",
"description": "Per-row results of an import commit.",
"required": [
"total",
"imported",
"updated",
"skipped",
"failed",
"started_at",
"ended_at"
],
"properties": {
"total": {
"type": "integer"
},
"imported": {
"type": "integer"
},
"updated": {
"type": "integer"
},
"skipped": {
"type": "integer"
},
"failed": {
"type": "integer"
},
"started_at": {
"type": "string",
"format": "date-time"
},
"ended_at": {
"type": "string",
"format": "date-time"
},
"errors": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactImportRowError"
}
}
}
},
"ContactLookupResult": {
"type": "object",
"description": "Resolved contact for a sender address; contact is null when nothing matches.",
"required": [
"contact"
],
"properties": {
"contact": {
"allOf": [
{
"$ref": "#/components/schemas/Contact"
}
]
}
}
},
"ContactSentEmail": {
"type": "object",
"description": "One email sent (or attempted) to a contact.",
"required": [
"task_id",
"status",
"message_id",
"subject",
"sent_at"
],
"properties": {
"task_id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string"
},
"message_id": {
"type": "string"
},
"subject": {
"type": "string"
},
"sent_at": {
"type": "string",
"format": "date-time"
},
"email_account_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"email_account_email": {
"type": [
"string",
"null"
]
},
"email_account_name": {
"type": [
"string",
"null"
]
},
"campaign_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"campaign_name": {
"type": [
"string",
"null"
]
},
"step_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"step_name": {
"type": [
"string",
"null"
]
},
"opened_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"clicked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"replied_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"bounced_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"ContactSentEmailList": {
"type": "object",
"description": "A page of emails sent to a contact.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactSentEmail"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"ContactTimelineEvent": {
"type": "object",
"description": "One entry in a contact's merged activity feed. Fields not relevant to the event type are omitted.",
"required": [
"type",
"at"
],
"properties": {
"type": {
"type": "string",
"enum": [
"email_sent",
"email_opened",
"email_clicked",
"email_replied",
"email_bounced",
"reply_received",
"deliverability",
"suppressed",
"note",
"meeting_booked",
"meeting_rescheduled",
"meeting_canceled",
"contact_created",
"campaign_added",
"campaign_removed",
"category_added",
"category_removed",
"form_submitted",
"page_hit"
]
},
"at": {
"type": "string",
"format": "date-time"
},
"email_account_id": {
"type": "string",
"format": "uuid"
},
"email_account_email": {
"type": "string"
},
"email_account_name": {
"type": "string"
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"campaign_name": {
"type": "string"
},
"step_id": {
"type": "string",
"format": "uuid"
},
"step_name": {
"type": "string"
},
"task_id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"reason": {
"type": "string",
"description": "Deliverability / suppression / meeting cancellation reason."
},
"source": {
"type": "string",
"description": "Suppression: bounce/complaint/unsubscribe; meeting: calendly/cal_com."
},
"provider": {
"type": "string"
},
"intent": {
"type": "string",
"description": "reply_intent classification."
},
"content": {
"type": "string",
"description": "Note body."
},
"scheduled_for": {
"type": "string",
"format": "date-time",
"description": "When the call is set for (meeting events)."
},
"join_url": {
"type": "string"
},
"meeting_state": {
"type": "string",
"enum": [
"booked",
"rescheduled",
"canceled"
]
},
"user_id": {
"type": "string",
"format": "uuid",
"description": "Note author."
},
"machine": {
"type": [
"boolean",
"null"
],
"description": "email_opened / email_clicked: true when an automated fetcher (a mail privacy proxy, a security gateway following links) did it rather than the person."
},
"machine_reason": {
"type": [
"string",
"null"
],
"description": "Which rule caught a machine open or click: prefetch, instant or burst. Absent on an open summarised from the lead alone."
},
"link": {
"oneOf": [
{
"$ref": "#/components/schemas/ContactLinkClick"
},
{
"type": "null"
}
],
"description": "email_clicked: the exact link clicked. Absent on clicks recorded before per-link attribution."
},
"origin": {
"oneOf": [
{
"$ref": "#/components/schemas/EngagementOrigin"
},
{
"type": "null"
}
],
"description": "email_opened / email_clicked: where the event came from, when it was logged per event."
},
"category_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "category_added / category_removed: the category, as it was at the time."
},
"category_title": {
"type": [
"string",
"null"
],
"description": "category_added / category_removed: the category's title at the time."
},
"source_detail": {
"type": [
"string",
"null"
],
"description": "contact_created: the file, campaign, sheet or API key name behind `source`."
},
"form_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "form_submitted: the hosted form."
},
"form_name": {
"type": [
"string",
"null"
],
"description": "form_submitted: the form's name."
},
"page_hit": {
"oneOf": [
{
"$ref": "#/components/schemas/WebsitePageHit"
},
{
"type": "null"
}
],
"description": "page_hit: the page view from the website tracking snippet. `subject` carries the page title, or its path when untitled."
}
}
},
"ContactTimelineResult": {
"type": "object",
"description": "A page of timeline events. Paginate with pagination.next_cursor as the `cursor` query param. has_more mirrors pagination.has_more and is kept for older clients.",
"required": [
"data",
"has_more",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactTimelineEvent"
}
},
"has_more": {
"type": "boolean"
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"ContactActivity": {
"type": "object",
"description": "One structured CRM activity-log entry.",
"required": [
"id",
"contact_id",
"organization_id",
"activity_type",
"metadata",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"contact_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"activity_type": {
"type": "string",
"enum": [
"email_sent",
"email_opened",
"email_clicked",
"email_replied",
"email_bounced",
"note_added",
"note_updated",
"deal_created",
"deal_stage_changed",
"deal_won",
"deal_lost",
"task_created",
"task_completed",
"contact_created",
"contact_updated",
"campaign_added",
"campaign_removed"
]
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"user": {
"type": "object",
"additionalProperties": true,
"description": "Joined user record, when present."
}
}
},
"ContactActivityList": {
"type": "object",
"description": "A page of CRM activities.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactActivity"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"ContactNote": {
"type": "object",
"description": "A CRM note attached to a contact.",
"required": [
"id",
"contact_id",
"organization_id",
"user_id",
"content",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"contact_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid"
},
"content": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"user": {
"type": "object",
"additionalProperties": true,
"description": "Joined author record, when present."
}
}
},
"ContactNoteList": {
"type": "object",
"description": "A page of contact notes.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ContactNote"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"ContactNoteCreate": {
"type": "object",
"description": "Body to create a contact note.",
"required": [
"content"
],
"properties": {
"content": {
"type": "string",
"minLength": 1,
"maxLength": 10000,
"description": "Note body (1 to 10,000 characters)."
}
}
},
"ContactNoteUpdate": {
"type": "object",
"description": "Body to edit a contact note.",
"properties": {
"content": {
"type": "string",
"maxLength": 10000,
"description": "New note body."
}
}
},
"Deal": {
"type": "object",
"description": "A CRM deal. Nullable attribution fields are omitted when unset.",
"required": [
"id",
"organization_id",
"pipeline_id",
"stage_id",
"name",
"currency",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"pipeline_id": {
"type": "string",
"format": "uuid"
},
"stage_id": {
"type": "string",
"format": "uuid"
},
"contact_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"name": {
"type": "string"
},
"value": {
"type": [
"number",
"null"
]
},
"currency": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"open",
"won",
"lost"
]
},
"expected_close_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"won_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"lost_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"lost_reason": {
"type": [
"string",
"null"
]
},
"assigned_to": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"campaign_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"source_mailbox_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"UniboxLabel": {
"type": "object",
"description": "A conversation label (one of the caller's categories).",
"required": [
"id",
"title",
"color"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string"
},
"color": {
"type": "string",
"description": "Hex color, e.g. `#16a34a`."
}
}
},
"UniboxThread": {
"type": "object",
"description": "One inbox row, summarising the newest message of a thread plus thread-level rollups.",
"required": [
"id",
"email_id",
"thread_id",
"subject",
"internal_date",
"seen",
"message_count",
"has_unread"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "UUID of the newest message in the thread."
},
"email_id": {
"type": "string",
"format": "uuid",
"description": "UUID of the mailbox the message landed in."
},
"thread_id": {
"type": "string",
"description": "Thread identifier."
},
"from_addr": {
"type": "array",
"items": {
"type": "string"
}
},
"to_addr": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"snippet": {
"type": "string"
},
"internal_date": {
"type": "string",
"format": "date-time"
},
"seen": {
"type": "boolean",
"description": "Whether the newest message is read."
},
"message_count": {
"type": "integer",
"description": "Number of messages in the thread."
},
"has_unread": {
"type": "boolean",
"description": "Whether the thread has any unread message."
},
"labels": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxLabel"
}
}
}
},
"UniboxThreadList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxThread"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"UniboxMessage": {
"type": "object",
"description": "A full message row inside a thread (envelope plus body).",
"required": [
"id",
"email_id",
"thread_id",
"subject",
"internal_date",
"seen"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"email_id": {
"type": "string",
"format": "uuid",
"description": "UUID of the mailbox the message landed in."
},
"mailbox": {
"type": "integer",
"description": "IMAP mailbox/folder index."
},
"thread_id": {
"type": "string"
},
"message_id": {
"type": "string",
"description": "RFC Message-ID header."
},
"gmail_id": {
"type": "string"
},
"parent_id": {
"type": "string"
},
"uid": {
"type": "integer"
},
"mod_seq": {
"type": "integer"
},
"flags": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"from_addr": {
"type": "array",
"items": {
"type": "string"
}
},
"in_reply_to": {
"type": "array",
"items": {
"type": "string"
}
},
"reply_to": {
"type": "array",
"items": {
"type": "string"
}
},
"to_addr": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"size": {
"type": "integer",
"description": "Raw message size in bytes."
},
"internal_date": {
"type": "string",
"format": "date-time"
},
"sent_date": {
"type": "string",
"format": "date-time"
},
"snippet": {
"type": "string"
},
"seen": {
"type": "boolean"
},
"body_plain": {
"type": "string"
},
"body_html": {
"type": "string"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"UniboxMessageList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxMessage"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"UniboxEmail": {
"type": "object",
"description": "A single message fetched by id. Note the field names differ from the thread message shape (e.g. `from`/`to`/`date`).",
"required": [
"id",
"thread_id",
"subject"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"gmail_id": {
"type": "string"
},
"uid": {
"type": "integer"
},
"parent_id": {
"type": "string"
},
"thread_id": {
"type": "string"
},
"flags": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"date": {
"type": "string",
"format": "date-time",
"description": "Sent date."
},
"from": {
"type": "array",
"items": {
"type": "string"
}
},
"in_reply_to": {
"type": "array",
"items": {
"type": "string"
}
},
"message_id": {
"type": "string",
"description": "RFC Message-ID header."
},
"ReplyTo": {
"type": "array",
"items": {
"type": "string"
},
"description": "Reply-To addresses (serialized as `ReplyTo`)."
},
"to": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"size": {
"type": "integer"
},
"internal_date": {
"type": "string",
"format": "date-time"
},
"mod_seq": {
"type": "integer"
},
"body_plain": {
"type": "string",
"description": "Plain-text body. Falls back to the preview snippet when body_truncated is true."
},
"body_html": {
"type": "string",
"description": "Sanitized HTML body: scripts, event handlers, embedded frames and unsafe URL schemes are removed, and links carry target=_blank with rel=noopener. Safe to render."
},
"body_truncated": {
"type": "boolean",
"description": "True when the stored body could not be read, so body_plain holds only the preview snippet."
}
}
},
"UniboxCount": {
"type": "object",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"description": "Org-wide unread message count."
}
}
},
"UniboxOverviewMailbox": {
"type": "object",
"required": [
"id",
"email",
"unread",
"total"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"name": {
"type": "string"
},
"unread": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
},
"UniboxOverviewBucket": {
"type": "object",
"description": "A tag or conversation-label breakdown bucket.",
"required": [
"id",
"title",
"unread",
"total"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string"
},
"color": {
"type": "string"
},
"unread": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
},
"UniboxOverview": {
"type": "object",
"required": [
"total",
"unread",
"today",
"week",
"snoozed",
"awaiting_reply",
"scheduled_pending"
],
"properties": {
"total": {
"type": "integer"
},
"unread": {
"type": "integer"
},
"today": {
"type": "integer"
},
"week": {
"type": "integer"
},
"snoozed": {
"type": "integer"
},
"awaiting_reply": {
"type": "integer"
},
"scheduled_pending": {
"type": "integer"
},
"scheduled_pending_max": {
"type": "integer",
"description": "Max queued scheduled sends allowed."
},
"folders": {
"type": "array",
"description": "Per-folder thread counts, always all six canonical folders in sidebar order, zero-filled.",
"items": {
"$ref": "#/components/schemas/UniboxOverviewFolder"
}
},
"mailboxes": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxOverviewMailbox"
}
},
"tags": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxOverviewBucket"
}
},
"categories": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxOverviewBucket"
}
},
"generated_at": {
"type": "string",
"format": "date-time"
},
"window_today_start": {
"type": "string",
"format": "date-time"
},
"window_week_start": {
"type": "string",
"format": "date-time"
}
}
},
"UniboxOverviewFolder": {
"type": "object",
"required": [
"folder",
"unread",
"total"
],
"properties": {
"folder": {
"type": "string",
"enum": [
"inbox",
"sent",
"drafts",
"archive",
"spam",
"trash"
]
},
"unread": {
"type": "integer"
},
"total": {
"type": "integer"
}
}
},
"UniboxLabelList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxLabel"
}
}
}
},
"UniboxSetThreadLabelsRequest": {
"type": "object",
"required": [
"thread_id"
],
"properties": {
"thread_id": {
"type": "string",
"description": "The thread to label."
},
"category_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Full desired set of category UUIDs. An empty array clears all labels."
}
}
},
"UniboxMarkSeenRequest": {
"type": "object",
"description": "Also the echoed response body. Send one of `email_ids` or `folder`, not both.",
"properties": {
"email_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"maxItems": 500,
"description": "Message UUIDs to update (max 500)."
},
"folder": {
"type": "string",
"enum": [
"inbox",
"sent",
"drafts",
"archive",
"spam",
"trash"
],
"description": "Sweep every message in this canonical folder instead of an id list."
},
"seen": {
"type": "boolean",
"description": "`true` marks as read, `false` marks as unread."
}
}
},
"UniboxMoveFolderRequest": {
"type": "object",
"description": "Also the echoed response body.",
"required": [
"email_ids",
"folder"
],
"properties": {
"email_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"maxItems": 500,
"description": "Message UUIDs to move (max 500)."
},
"folder": {
"type": "string",
"enum": [
"inbox",
"archive",
"trash"
],
"description": "Destination folder. Anything else is a `400`."
}
}
},
"UniboxReplyRequest": {
"type": "object",
"required": [
"email_account_id",
"to",
"subject"
],
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid",
"description": "UUID of the sending mailbox."
},
"to": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"description": "Recipient addresses (at least one)."
},
"cc": {
"type": "array",
"items": {
"type": "string"
}
},
"bcc": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"in_reply_to": {
"type": "array",
"items": {
"type": "string"
},
"description": "Message-ID(s) this reply threads under."
},
"thread_id": {
"type": "string"
},
"send_mode": {
"type": "string",
"enum": [
"instant",
"smart",
"scheduled"
],
"default": "instant",
"description": "`instant`, `smart` (next mailbox gap), or `scheduled`."
},
"scheduled_at": {
"type": "string",
"format": "date-time",
"description": "Required when `send_mode` is `scheduled`; must be in the future."
}
}
},
"UniboxReplyResult": {
"type": "object",
"required": [
"task_id",
"scheduled_at",
"send_mode"
],
"properties": {
"task_id": {
"type": "string",
"format": "uuid"
},
"scheduled_at": {
"type": "string",
"format": "date-time",
"description": "When the send is scheduled to fire."
},
"send_mode": {
"type": "string",
"enum": [
"instant",
"smart",
"scheduled"
]
}
}
},
"UniboxSnoozeRequest": {
"type": "object",
"required": [
"thread_id",
"snoozed_until"
],
"properties": {
"thread_id": {
"type": "string",
"description": "The thread to snooze."
},
"snoozed_until": {
"type": "string",
"format": "date-time",
"description": "RFC 3339 timestamp to un-hide the thread."
}
}
},
"UniboxSnooze": {
"type": "object",
"required": [
"id",
"user_id",
"thread_id",
"snoozed_until"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid",
"description": "Snoozes are attached to the calling user."
},
"thread_id": {
"type": "string"
},
"snoozed_until": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"UniboxSnoozeList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxSnooze"
}
}
}
},
"UniboxScheduledSend": {
"type": "object",
"description": "A preview of a queued, not-yet-sent outbound message.",
"required": [
"task_id",
"scheduled_at",
"account_id",
"subject"
],
"properties": {
"task_id": {
"type": "string",
"format": "uuid"
},
"scheduled_at": {
"type": "string",
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"account_id": {
"type": "string",
"format": "uuid",
"description": "UUID of the sending mailbox."
},
"account_email": {
"type": "string"
},
"account_name": {
"type": "string"
},
"to": {
"type": "array",
"items": {
"type": "string"
}
},
"subject": {
"type": "string"
},
"snippet": {
"type": "string"
},
"thread_id": {
"type": "string"
}
}
},
"UniboxScheduledList": {
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UniboxScheduledSend"
}
}
}
},
"Pipeline": {
"type": "object",
"description": "A sales pipeline with its ordered stages.",
"required": [
"id",
"organization_id",
"name",
"position",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"position": {
"type": "integer"
},
"stages": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PipelineStage"
}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"PipelineStage": {
"type": "object",
"description": "A stage within a pipeline.",
"required": [
"id",
"pipeline_id",
"name",
"color",
"position",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"pipeline_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"color": {
"type": "string",
"description": "Hex color."
},
"position": {
"type": "integer"
},
"deal_count": {
"type": "integer",
"description": "Count of deals in this stage (populated by the pipeline list/get queries)."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CreatePipeline": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Pipeline name."
},
"stages": {
"type": "array",
"description": "Stages to create with the pipeline, in order.",
"items": {
"$ref": "#/components/schemas/CreatePipelineStage"
}
}
}
},
"CreatePipelineStage": {
"type": "object",
"required": [
"name",
"color"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Stage name."
},
"color": {
"type": "string",
"description": "Stage color (hex)."
}
}
},
"UpdatePipeline": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "New pipeline name."
}
}
},
"UpdatePipelineStage": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "New stage name."
},
"color": {
"type": "string",
"description": "New stage color (hex)."
}
}
},
"DealList": {
"type": "object",
"description": "Keyset-paginated page of deals.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Deal"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"CreateDeal": {
"type": "object",
"required": [
"pipeline_id",
"stage_id",
"name"
],
"properties": {
"pipeline_id": {
"type": "string",
"format": "uuid",
"description": "Pipeline the deal belongs to."
},
"stage_id": {
"type": "string",
"format": "uuid",
"description": "Initial stage."
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "Linked contact."
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Deal name."
},
"value": {
"type": "number",
"description": "Monetary value."
},
"currency": {
"type": "string",
"description": "ISO currency code."
},
"expected_close_date": {
"type": "string",
"format": "date-time",
"description": "Expected close date."
},
"assigned_to": {
"type": "string",
"format": "uuid",
"description": "Owner (org member user ID)."
},
"campaign_id": {
"type": "string",
"format": "uuid",
"description": "Attributed campaign."
},
"source_mailbox_id": {
"type": "string",
"format": "uuid",
"description": "Sending mailbox that produced the originating reply."
}
}
},
"UpdateDeal": {
"type": "object",
"description": "All fields optional. Moving stage_id records a stage-change activity; setting status to won/lost stamps the close timestamp.",
"properties": {
"stage_id": {
"type": "string",
"format": "uuid",
"description": "Move the deal to this stage."
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "Linked contact."
},
"name": {
"type": "string",
"description": "Deal name."
},
"value": {
"type": "number",
"description": "Monetary value."
},
"currency": {
"type": "string",
"description": "ISO currency code."
},
"status": {
"type": "string",
"enum": [
"open",
"won",
"lost"
]
},
"expected_close_date": {
"type": "string",
"format": "date-time"
},
"lost_reason": {
"type": "string",
"description": "Reason recorded when marking lost."
},
"assigned_to": {
"type": "string",
"format": "uuid",
"description": "Owner (org member user ID)."
}
}
},
"SearchDeals": {
"type": "object",
"description": "Faceted deal filter body shared by deal search and deal summary. All facets optional; an empty body matches every deal.",
"properties": {
"query": {
"type": "string",
"description": "Case-insensitive match on deal name."
},
"statuses": {
"type": "array",
"items": {
"type": "string",
"enum": [
"open",
"won",
"lost"
]
}
},
"pipeline_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"stage_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"assigned_to": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Owner is any of these user IDs."
},
"campaign_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"min_value": {
"type": "number",
"description": "Value greater than or equal to."
},
"max_value": {
"type": "number",
"description": "Value less than or equal to."
},
"close_after": {
"type": "string",
"format": "date-time",
"description": "Expected close date on or after."
},
"close_before": {
"type": "string",
"format": "date-time",
"description": "Expected close date on or before."
},
"created_after": {
"type": "string",
"format": "date-time"
},
"created_before": {
"type": "string",
"format": "date-time"
},
"sort_by": {
"type": "string",
"enum": [
"created_at",
"updated_at",
"value",
"expected_close_date",
"name"
]
},
"reverse": {
"type": "boolean",
"description": "true sorts ascending, false (default) descending."
}
}
},
"DealsSearchResult": {
"type": "object",
"description": "Offset-paginated deal search result with an exact total.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Deal"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"DealsSummary": {
"type": "object",
"description": "Aggregate counts and value sums over a deal search filter body. mixed_currency true means top-level value sums should be treated as approximate.",
"required": [
"total",
"open_count",
"open_value",
"won_count",
"won_value",
"lost_count",
"lost_value",
"currency",
"stages",
"mixed_currency"
],
"properties": {
"total": {
"type": "integer",
"format": "int64"
},
"open_count": {
"type": "integer",
"format": "int64"
},
"open_value": {
"type": "number"
},
"won_count": {
"type": "integer",
"format": "int64"
},
"won_value": {
"type": "number"
},
"lost_count": {
"type": "integer",
"format": "int64"
},
"lost_value": {
"type": "number"
},
"currency": {
"type": "string"
},
"stages": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DealStageSummary"
}
},
"mixed_currency": {
"type": "boolean"
}
}
},
"DealStageSummary": {
"type": "object",
"required": [
"stage_id",
"count",
"value"
],
"properties": {
"stage_id": {
"type": "string",
"format": "uuid"
},
"count": {
"type": "integer",
"format": "int64"
},
"value": {
"type": "number",
"description": "Open-deal value in this stage."
}
}
},
"CRMTaskType": {
"type": "object",
"description": "A user-managed CRM task type (the kind of work a task represents).",
"required": [
"id",
"organization_id",
"name",
"color",
"position",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"color": {
"type": "string",
"description": "Hex color."
},
"position": {
"type": "integer"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CRMTaskTypeList": {
"type": "object",
"description": "Task types (no pagination envelope).",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CRMTaskType"
}
}
}
},
"CreateCRMTaskType": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 60,
"description": "Type name."
},
"color": {
"type": "string",
"description": "Type color (hex)."
}
}
},
"UpdateCRMTaskType": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "New type name."
},
"color": {
"type": "string",
"description": "New type color (hex)."
},
"position": {
"type": "integer",
"description": "New ordering position."
}
}
},
"CRMTask": {
"type": "object",
"description": "A CRM task (follow-up work attached to contacts and deals).",
"required": [
"id",
"organization_id",
"created_by",
"title",
"priority",
"type",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"contact_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"deal_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"assigned_to": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Assignee user ID."
},
"assigned_team_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Assignee team ID."
},
"created_by": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string"
},
"description": {
"type": [
"string",
"null"
]
},
"due_date": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"priority": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"urgent"
]
},
"type": {
"type": "string",
"description": "Task type name."
},
"status": {
"type": "string",
"enum": [
"pending",
"in_progress",
"completed",
"cancelled"
]
},
"completed_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CRMTaskList": {
"type": "object",
"description": "Keyset-paginated page of CRM tasks.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CRMTask"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"CreateCRMTask": {
"type": "object",
"required": [
"title"
],
"properties": {
"title": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"description": "Task title."
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "Linked contact."
},
"deal_id": {
"type": "string",
"format": "uuid",
"description": "Linked deal."
},
"assigned_to": {
"type": "string",
"format": "uuid",
"description": "Assignee user ID."
},
"assigned_team_id": {
"type": "string",
"format": "uuid",
"description": "Assignee team ID."
},
"description": {
"type": "string",
"description": "Free-text description."
},
"due_date": {
"type": "string",
"format": "date-time",
"description": "Due date."
},
"priority": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"urgent"
]
},
"type": {
"type": "string",
"description": "Task type name (matches a configured task type)."
}
}
},
"UpdateCRMTask": {
"type": "object",
"description": "All fields optional. Setting status to completed stamps the completion timestamp.",
"properties": {
"title": {
"type": "string",
"description": "Task title."
},
"assigned_to": {
"type": "string",
"format": "uuid",
"description": "Assignee user ID."
},
"assigned_team_id": {
"type": "string",
"format": "uuid",
"description": "Assignee team ID."
},
"description": {
"type": "string",
"description": "Free-text description."
},
"due_date": {
"type": "string",
"format": "date-time",
"description": "Due date."
},
"priority": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"urgent"
]
},
"type": {
"type": "string",
"description": "Task type name."
},
"status": {
"type": "string",
"enum": [
"pending",
"in_progress",
"completed",
"cancelled"
]
}
}
},
"SearchTasks": {
"type": "object",
"description": "Faceted task filter body shared by task search and task summary. All facets optional; an empty body matches every task.",
"properties": {
"query": {
"type": "string",
"description": "Case-insensitive match on task title."
},
"statuses": {
"type": "array",
"items": {
"type": "string",
"enum": [
"pending",
"in_progress",
"completed",
"cancelled"
]
}
},
"priorities": {
"type": "array",
"items": {
"type": "string",
"enum": [
"low",
"medium",
"high",
"urgent"
]
}
},
"types": {
"type": "array",
"items": {
"type": "string"
},
"description": "Task type name is any of these."
},
"assigned_to": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Assignee user ID is any of these."
},
"team_ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Task team is any of these, or the assignee belongs to one."
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "Linked contact."
},
"deal_id": {
"type": "string",
"format": "uuid",
"description": "Linked deal."
},
"due_after": {
"type": "string",
"format": "date-time",
"description": "Due on or after."
},
"due_before": {
"type": "string",
"format": "date-time",
"description": "Due on or before."
},
"overdue": {
"type": "boolean",
"description": "Only tasks past due and not completed or cancelled."
},
"sort_by": {
"type": "string",
"enum": [
"created_at",
"due_date",
"priority",
"title",
"updated_at"
]
},
"reverse": {
"type": "boolean",
"description": "true sorts ascending, false (default) descending."
}
}
},
"TasksSearchResult": {
"type": "object",
"description": "Offset-paginated task search result with an exact total.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CRMTask"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"TasksSummary": {
"type": "object",
"description": "Aggregate task counts over a task search filter body.",
"required": [
"total",
"pending_count",
"in_progress_count",
"completed_count",
"cancelled_count",
"overdue_count",
"high_priority_count"
],
"properties": {
"total": {
"type": "integer",
"format": "int64"
},
"pending_count": {
"type": "integer",
"format": "int64"
},
"in_progress_count": {
"type": "integer",
"format": "int64"
},
"completed_count": {
"type": "integer",
"format": "int64"
},
"cancelled_count": {
"type": "integer",
"format": "int64"
},
"overdue_count": {
"type": "integer",
"format": "int64"
},
"high_priority_count": {
"type": "integer",
"format": "int64"
}
}
},
"APIKey": {
"type": "object",
"description": "An API key without its plaintext secret.",
"required": [
"id",
"user_id",
"organization_id",
"name",
"key_prefix",
"key_suffix",
"permissions",
"rate_limit_per_minute",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid",
"description": "The member who created the key."
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string",
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form note about the key's purpose."
},
"key_prefix": {
"type": "string",
"description": "Short display prefix of the secret (e.g. wmbly_3f)."
},
"key_suffix": {
"type": "string",
"description": "Short display suffix of the secret."
},
"permissions": {
"type": "integer",
"format": "int64",
"description": "uint64 permission bitmask. Combine bits with bitwise OR; the key may perform a request only when its mask contains every required bit. See GET /api-keys/permissions for bit names and values."
},
"allowed_ips": {
"type": "array",
"items": {
"type": "string"
},
"description": "If non-empty, the key is usable only from these source IPs."
},
"allowed_email_accounts": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "If non-empty, mailbox-scoped routes accept only these email account ids."
},
"rate_limit_per_minute": {
"type": "integer",
"description": "Per-key sliding-window request cap. 0 means the default (60 r/m)."
},
"status": {
"$ref": "#/components/schemas/APIKeyStatus"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_request_ip": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the key stops working. Null for a non-expiring key."
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"revoked_reason": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"APIKeyStatus": {
"type": "string",
"enum": [
"active",
"revoked",
"expired"
],
"description": "Lifecycle status of the key."
},
"APIKeyWithSecret": {
"type": "object",
"description": "An API key plus the one-time plaintext secret, returned only on creation.",
"allOf": [
{
"$ref": "#/components/schemas/APIKey"
},
{
"type": "object",
"required": [
"secret"
],
"properties": {
"secret": {
"type": "string",
"description": "The full plaintext key. Returned only once, at creation; it cannot be recovered later."
}
}
}
]
},
"APIKeyList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/APIKey"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"CreateAPIKey": {
"type": "object",
"required": [
"name",
"permissions"
],
"properties": {
"name": {
"type": "string",
"maxLength": 255,
"description": "Human-readable label."
},
"description": {
"type": "string",
"description": "Free-form note about the key's purpose."
},
"permissions": {
"type": "integer",
"format": "int64",
"description": "uint64 permission bitmask. Must contain only defined bits; unknown bits are rejected."
},
"allowed_ips": {
"type": "array",
"items": {
"type": "string"
},
"description": "If set, the key is usable only from these source IPs. Omit or leave empty to allow any IP."
},
"allowed_email_accounts": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "If set, mailbox-scoped routes accept only these email account ids."
},
"rate_limit_per_minute": {
"type": "integer",
"description": "Per-key request cap. Omit or send 0 to use the default (60 r/m)."
},
"expires_at": {
"type": "string",
"format": "date-time",
"description": "When the key should stop working (RFC3339). Omit for a non-expiring key."
}
}
},
"UpdateAPIKey": {
"type": "object",
"description": "Every field is optional; only the fields you send are changed.",
"properties": {
"name": {
"type": "string",
"description": "New label."
},
"description": {
"type": "string",
"description": "New description."
},
"permissions": {
"type": "integer",
"format": "int64",
"description": "Replacement uint64 permission bitmask."
},
"allowed_ips": {
"type": "array",
"items": {
"type": "string"
},
"description": "Replacement IP allowlist."
},
"allowed_email_accounts": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Replacement mailbox allowlist."
},
"rate_limit_per_minute": {
"type": "integer",
"description": "New per-key rate cap. 0 means use the default."
}
}
},
"APIKeyRevokeResult": {
"type": "object",
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"enum": [
"revoked"
]
}
}
},
"APIKeyDeleteResult": {
"type": "object",
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"enum": [
"deleted"
]
}
}
},
"APIPermission": {
"type": "object",
"required": [
"name",
"value",
"description",
"category"
],
"properties": {
"name": {
"type": "string",
"description": "Bit name, e.g. READ_EMAILS."
},
"value": {
"type": "integer",
"format": "int64",
"description": "Numeric bit value."
},
"description": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"read",
"write",
"bulk",
"special"
]
}
}
},
"APIPermissionCatalog": {
"type": "object",
"required": [
"permissions",
"presets"
],
"properties": {
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/APIPermission"
}
},
"presets": {
"type": "object",
"required": [
"read_only",
"full_access"
],
"properties": {
"read_only": {
"type": "integer",
"format": "int64",
"description": "Bitmask granting all read scopes."
},
"full_access": {
"type": "integer",
"format": "int64",
"description": "Bitmask granting every scope."
}
}
}
}
},
"APIKeyUsageSummary": {
"type": "object",
"description": "Org-level usage strip. The 24h fields cover the last 24 hours.",
"required": [
"active_keys",
"revoked_keys",
"expired_keys",
"requests_24h",
"errors_24h",
"avg_latency_ms_24h"
],
"properties": {
"active_keys": {
"type": "integer"
},
"revoked_keys": {
"type": "integer"
},
"expired_keys": {
"type": "integer"
},
"requests_24h": {
"type": "integer",
"format": "int64"
},
"errors_24h": {
"type": "integer",
"format": "int64"
},
"avg_latency_ms_24h": {
"type": "number"
},
"last_call_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"APIKeyUsageBucket": {
"type": "object",
"description": "One point on a time-bucketed request graph.",
"required": [
"bucket",
"total",
"success",
"client_errors",
"server_errors",
"avg_latency_ms"
],
"properties": {
"bucket": {
"type": "string",
"format": "date-time"
},
"total": {
"type": "integer",
"format": "int64"
},
"success": {
"type": "integer",
"format": "int64",
"description": "2xx responses."
},
"client_errors": {
"type": "integer",
"format": "int64",
"description": "4xx responses."
},
"server_errors": {
"type": "integer",
"format": "int64",
"description": "5xx responses."
},
"avg_latency_ms": {
"type": "number"
}
}
},
"APIKeyEndpointStat": {
"type": "object",
"description": "One row in the per-endpoint breakdown.",
"required": [
"endpoint",
"method",
"count",
"error_count",
"avg_latency_ms"
],
"properties": {
"endpoint": {
"type": "string"
},
"method": {
"type": "string"
},
"count": {
"type": "integer",
"format": "int64"
},
"error_count": {
"type": "integer",
"format": "int64"
},
"avg_latency_ms": {
"type": "number"
}
}
},
"APIKeyAnalytics": {
"type": "object",
"required": [
"api_key_id",
"from",
"to",
"interval",
"buckets",
"endpoints",
"total",
"errors"
],
"properties": {
"api_key_id": {
"type": "string",
"format": "uuid",
"description": "The key id, or the all-zero UUID for the org-wide aggregate."
},
"from": {
"type": "string",
"format": "date-time"
},
"to": {
"type": "string",
"format": "date-time"
},
"interval": {
"type": "string",
"enum": [
"minute",
"hour",
"day"
]
},
"buckets": {
"type": "array",
"items": {
"$ref": "#/components/schemas/APIKeyUsageBucket"
}
},
"endpoints": {
"type": "array",
"items": {
"$ref": "#/components/schemas/APIKeyEndpointStat"
}
},
"total": {
"type": "integer",
"format": "int64"
},
"errors": {
"type": "integer",
"format": "int64"
}
}
},
"APIKeyUsageLog": {
"type": "object",
"description": "One recorded request made with the key.",
"required": [
"id",
"api_key_id",
"endpoint",
"method",
"ip_address",
"user_agent",
"response_code",
"response_time_ms",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"api_key_id": {
"type": "string",
"format": "uuid"
},
"endpoint": {
"type": "string"
},
"method": {
"type": "string"
},
"ip_address": {
"type": "string"
},
"user_agent": {
"type": "string"
},
"response_code": {
"type": "integer"
},
"response_time_ms": {
"type": "integer"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"APIKeyUsageLogList": {
"type": "object",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/APIKeyUsageLog"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"WebhookEventType": {
"type": "string",
"description": "Canonical event name carried in the subscription filter and the delivery payload. An endpoint with an empty `event_types` filter receives all of these.",
"enum": [
"email_account.connected",
"email_account.removed",
"campaign.email_sent",
"campaign.email_delivered",
"campaign.email_opened",
"campaign.email_clicked",
"campaign.email_bounced",
"campaign.reply_received",
"campaign.unsubscribed",
"campaign.started",
"campaign.paused",
"campaign.completed",
"campaign.deliverability_warning",
"campaign.action",
"warmup.email_sent",
"warmup.health_changed",
"warmup.placement_in_spam",
"warmup.quarantined",
"warmup.blocked",
"deliverability.bounce",
"deliverability.complaint",
"meeting.booked",
"meeting.rescheduled",
"meeting.canceled"
]
},
"WebhookEndpoint": {
"type": "object",
"description": "A customer's subscription to events. Returned without the signing secret on all reads and updates.",
"required": [
"id",
"organization_id",
"url",
"description",
"event_types",
"enabled",
"consecutive_failures",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string",
"format": "uri",
"description": "HTTPS URL that receives POST callbacks."
},
"description": {
"type": "string",
"description": "Free-text label for your own reference."
},
"event_types": {
"type": "array",
"description": "Subscribed event names. An empty array means all events.",
"items": {
"$ref": "#/components/schemas/WebhookEventType"
}
},
"enabled": {
"type": "boolean",
"description": "Whether the endpoint is active."
},
"last_success_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Time of the last successful delivery, or null."
},
"last_failure_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Time of the last failed delivery, or null."
},
"last_failure_reason": {
"type": [
"string",
"null"
],
"description": "Reason for the last failure, or null."
},
"consecutive_failures": {
"type": "integer",
"description": "Current run of consecutive delivery failures."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"WebhookEndpointWithSecret": {
"allOf": [
{
"$ref": "#/components/schemas/WebhookEndpoint"
},
{
"type": "object",
"required": [
"secret"
],
"properties": {
"secret": {
"type": "string",
"description": "The `whsec_`-prefixed HMAC signing secret. Returned only at create and rotate time."
}
}
}
]
},
"WebhookEndpointRequest": {
"type": "object",
"description": "Create/update body. The same body shape is used for both; on update all fields are replaced with the values sent (send the complete desired state). The secret is server-generated and cannot be set here.",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "HTTPS URL that will receive POST callbacks. Must be publicly routable."
},
"description": {
"type": "string",
"description": "Free-text label for your own reference."
},
"event_types": {
"type": "array",
"description": "Event names to subscribe to. Each must be a known type. An empty or omitted array subscribes to all events. On update this overwrites the existing filter (not merged).",
"items": {
"$ref": "#/components/schemas/WebhookEventType"
}
},
"enabled": {
"type": "boolean",
"default": true,
"description": "Whether the endpoint is active. Defaults to true."
}
}
},
"WebhookEndpointList": {
"type": "object",
"description": "List response. Not a `data` + `pagination` cursor envelope: it returns the configured endpoints plus the full event vocabulary.",
"required": [
"endpoints",
"event_types"
],
"properties": {
"endpoints": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WebhookEndpoint"
}
},
"event_types": {
"type": "array",
"description": "Every event Warmbly can emit, for building a picker.",
"items": {
"$ref": "#/components/schemas/WebhookEventType"
}
}
}
},
"WebhookSecretResponse": {
"type": "object",
"required": [
"secret"
],
"properties": {
"secret": {
"type": "string",
"description": "The new `whsec_`-prefixed HMAC signing secret. Returned only once."
}
}
},
"WebhookDeliveryStatus": {
"type": "string",
"description": "Lifecycle state of a delivery attempt. `abandoned` means retries were exhausted.",
"enum": [
"pending",
"in_flight",
"delivered",
"failed",
"abandoned"
]
},
"WebhookDelivery": {
"type": "object",
"description": "One delivery-history record. The row updates in place across retries; `attempt_count` and `status` reflect the latest state.",
"required": [
"id",
"endpoint_id",
"organization_id",
"event_type",
"event_id",
"payload",
"status",
"attempt_count",
"max_attempts",
"next_attempt_at",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"endpoint_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"event_type": {
"$ref": "#/components/schemas/WebhookEventType"
},
"event_id": {
"type": "string",
"format": "uuid",
"description": "Stable across retries. Matches the `X-Warmbly-Event-Id` header and the payload `id`."
},
"payload": {
"$ref": "#/components/schemas/WebhookPayload"
},
"status": {
"$ref": "#/components/schemas/WebhookDeliveryStatus"
},
"attempt_count": {
"type": "integer",
"description": "Number of delivery attempts made so far."
},
"max_attempts": {
"type": "integer",
"description": "Maximum attempts before the delivery is abandoned (default 8)."
},
"next_attempt_at": {
"type": "string",
"format": "date-time",
"description": "Scheduled time of the next retry."
},
"last_attempt_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"response_status": {
"type": [
"integer",
"null"
],
"description": "HTTP status returned by the subscriber on the last attempt, or null."
},
"response_body_excerpt": {
"type": [
"string",
"null"
],
"description": "First 1024 bytes of the subscriber's response, or null."
},
"error_reason": {
"type": [
"string",
"null"
],
"description": "Connection or timeout error from the last attempt, or null."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"WebhookDeliveryList": {
"type": "object",
"description": "Delivery list response, newest first. Not a `data` + `pagination` cursor envelope; bounded by the `limit` query param.",
"required": [
"deliveries"
],
"properties": {
"deliveries": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WebhookDelivery"
}
}
}
},
"WebhookPayload": {
"type": "object",
"description": "The JSON body POSTed to a subscriber endpoint. Signed with HMAC-SHA256: the `X-Warmbly-Signature` header is `t=<unix>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, \"<t>.\" + rawBody))`. Other headers: `X-Warmbly-Event` (event type), `X-Warmbly-Event-Id` (the event id for dedupe), `User-Agent: Warmbly-Webhooks/1.0`.",
"required": [
"id",
"event_type",
"organization_id",
"created_at",
"data"
],
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Unique event id, stable across retries. Matches `X-Warmbly-Event-Id`."
},
"event_type": {
"$ref": "#/components/schemas/WebhookEventType"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "RFC 3339 UTC timestamp of when the event was dispatched."
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "Event-specific payload. Shape depends on `event_type`."
}
}
},
"DashboardAnalytics": {
"type": "object",
"description": "Org-wide dashboard overview.",
"required": [
"period",
"overall_stats",
"recent_activity",
"top_campaigns",
"account_health",
"daily_trend"
],
"properties": {
"period": {
"type": "string",
"enum": [
"7d",
"30d",
"90d"
]
},
"overall_stats": {
"$ref": "#/components/schemas/OverallStats"
},
"recent_activity": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RecentActivity"
}
},
"top_campaigns": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TopCampaign"
}
},
"account_health": {
"$ref": "#/components/schemas/AccountHealthSummary"
},
"daily_trend": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DailyTrendPoint"
}
}
}
},
"OverallStats": {
"type": "object",
"properties": {
"total_emails_sent": {
"type": "integer"
},
"total_opens": {
"type": "integer"
},
"machine_opens": {
"type": "integer"
},
"total_clicks": {
"type": "integer"
},
"total_replies": {
"type": "integer"
},
"total_bounces": {
"type": "integer"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"bounce_rate": {
"type": "number"
},
"active_campaigns": {
"type": "integer"
},
"active_accounts": {
"type": "integer"
}
}
},
"RecentActivity": {
"type": "object",
"properties": {
"type": {
"type": "string",
"description": "Activity type, for example replied, opened, clicked."
},
"campaign_id": {
"type": "string",
"format": "uuid"
},
"campaign_name": {
"type": "string"
},
"contact_email": {
"type": "string"
},
"contact_id": {
"type": "string",
"format": "uuid"
},
"timestamp": {
"type": "string",
"format": "date-time"
}
}
},
"TopCampaign": {
"type": "object",
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"status": {
"type": "string"
},
"emails_sent": {
"type": "integer"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
}
}
},
"AccountHealthSummary": {
"type": "object",
"properties": {
"total_accounts": {
"type": "integer"
},
"healthy_accounts": {
"type": "integer"
},
"warning_accounts": {
"type": "integer"
},
"error_accounts": {
"type": "integer"
}
}
},
"DailyTrendPoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"sent": {
"type": "integer"
},
"opens": {
"type": "integer"
},
"clicks": {
"type": "integer"
},
"replies": {
"type": "integer"
}
}
},
"DeliverabilityDashboard": {
"type": "object",
"description": "Deliverability posture over a window. spam_placement_rate and inbox_placement_rate are omitted when there are no seed samples.",
"required": [
"from",
"to",
"band"
],
"properties": {
"from": {
"type": "string",
"format": "date-time"
},
"to": {
"type": "string",
"format": "date-time"
},
"events_total": {
"type": "integer"
},
"bounce_count": {
"type": "integer"
},
"complaint_count": {
"type": "integer"
},
"unsubscribe_count": {
"type": "integer"
},
"reply_count": {
"type": "integer"
},
"open_count": {
"type": "integer"
},
"click_count": {
"type": "integer"
},
"suppressed_recipients": {
"type": "integer"
},
"dlq_pending": {
"type": "integer"
},
"intent_positive": {
"type": "integer"
},
"intent_negative": {
"type": "integer"
},
"intent_out_of_office": {
"type": "integer"
},
"intent_question": {
"type": "integer"
},
"intent_neutral": {
"type": "integer"
},
"emails_sent": {
"type": "integer"
},
"bounce_rate": {
"type": "number"
},
"complaint_rate": {
"type": "number"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"spam_placement_rate": {
"type": "number",
"description": "Omitted when there are no seed samples in the window."
},
"inbox_placement_rate": {
"type": "number",
"description": "Omitted when there are no seed samples in the window."
},
"placement_samples": {
"type": "integer"
},
"band": {
"type": "string",
"description": "Overall health band.",
"enum": [
"healthy",
"watch",
"throttled",
"quarantined",
"blocked"
]
},
"timeseries": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeliverabilityDayPoint"
}
},
"by_mailbox": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeliverabilityMailbox"
}
},
"by_campaign": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeliverabilityCampaign"
}
}
}
},
"DeliverabilityDayPoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"sent": {
"type": "integer"
},
"bounces": {
"type": "integer"
},
"complaints": {
"type": "integer"
},
"opens": {
"type": "integer"
},
"clicks": {
"type": "integer"
},
"replies": {
"type": "integer"
},
"unsubscribes": {
"type": "integer"
}
}
},
"DeliverabilityMailbox": {
"type": "object",
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"sent": {
"type": "integer"
},
"bounces": {
"type": "integer"
},
"complaints": {
"type": "integer"
},
"bounce_rate": {
"type": "number"
},
"complaint_rate": {
"type": "number"
},
"band": {
"type": "string"
}
}
},
"DeliverabilityCampaign": {
"type": "object",
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"sent": {
"type": "integer"
},
"bounces": {
"type": "integer"
},
"complaints": {
"type": "integer"
},
"bounce_rate": {
"type": "number"
},
"complaint_rate": {
"type": "number"
},
"band": {
"type": "string"
}
}
},
"WarmupAnalytics": {
"type": "object",
"description": "Warmup send and reply statistics over a date range. email_account_id is the zero UUID when no email_id filter is supplied.",
"required": [
"email_account_id",
"date_range",
"summary",
"daily_stats"
],
"properties": {
"email_account_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"date_range": {
"$ref": "#/components/schemas/DateRange"
},
"summary": {
"$ref": "#/components/schemas/WarmupSummary"
},
"daily_stats": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WarmupDayPoint"
}
}
}
},
"WarmupSummary": {
"type": "object",
"properties": {
"total_sent": {
"type": "integer"
},
"total_replied": {
"type": "integer"
},
"average_daily": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"target_progress": {
"type": "number"
},
"days_active": {
"type": "integer"
}
}
},
"WarmupDayPoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"emails_sent": {
"type": "integer"
},
"emails_replied": {
"type": "integer"
},
"target_volume": {
"type": "integer"
}
}
},
"DateRange": {
"type": "object",
"properties": {
"from": {
"type": "string",
"format": "date-time"
},
"to": {
"type": "string",
"format": "date-time"
}
}
},
"CampaignAnalytics": {
"type": "object",
"description": "A single campaign's performance summary plus per-step stats.",
"required": [
"campaign_id",
"name",
"status",
"summary",
"steps"
],
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"status": {
"type": "string"
},
"date_range": {
"$ref": "#/components/schemas/DateRange"
},
"summary": {
"$ref": "#/components/schemas/CampaignAnalyticsSummary"
},
"steps": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignStepStats"
}
}
}
},
"CampaignAnalyticsSummary": {
"type": "object",
"description": "machine_opens is the subset of unique_opens from automated fetchers; human opens are unique_opens minus machine_opens.",
"properties": {
"total_contacts": {
"type": "integer"
},
"emails_sent": {
"type": "integer"
},
"emails_pending": {
"type": "integer"
},
"unique_opens": {
"type": "integer"
},
"machine_opens": {
"type": "integer"
},
"unique_clicks": {
"type": "integer"
},
"replies": {
"type": "integer"
},
"bounces": {
"type": "integer"
},
"unsubscribes": {
"type": "integer"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"bounce_rate": {
"type": "number"
}
}
},
"CampaignStepStats": {
"type": "object",
"properties": {
"step_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"position": {
"type": "integer"
},
"emails_sent": {
"type": "integer"
},
"opens": {
"type": "integer"
},
"machine_opens": {
"type": "integer",
"description": "Subset of opens from automated fetchers. Human opens are opens minus machine_opens."
},
"clicks": {
"type": "integer"
},
"machine_clicks": {
"type": "integer",
"description": "Contacts on this step whose only clicks were automated. Not part of clicks."
},
"replies": {
"type": "integer"
},
"bounces": {
"type": "integer"
},
"open_rate": {
"type": "number",
"format": "double",
"description": "Opens as a percentage of this step's own emails_sent. 0 while the step has sent nothing."
},
"click_rate": {
"type": "number",
"format": "double",
"description": "Clicks as a percentage of this step's own emails_sent. 0 while the step has sent nothing."
},
"reply_rate": {
"type": "number",
"format": "double",
"description": "Replies as a percentage of this step's own emails_sent. 0 while the step has sent nothing."
},
"bounce_rate": {
"type": "number",
"format": "double",
"description": "Bounces as a percentage of this step's own emails_sent. 0 while the step has sent nothing."
}
}
},
"CampaignDailyStats": {
"type": "object",
"description": "Per-day campaign series under a data envelope.",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignDayPoint"
}
}
}
},
"CampaignDayPoint": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"sent": {
"type": "integer"
},
"opens": {
"type": "integer"
},
"clicks": {
"type": "integer"
},
"replies": {
"type": "integer"
}
}
},
"CampaignHourlyStats": {
"type": "object",
"description": "Per-hour campaign series under a data envelope with the resolved date echoed back.",
"required": [
"data",
"date"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignHourPoint"
}
},
"date": {
"type": "string",
"format": "date"
}
}
},
"CampaignHourPoint": {
"type": "object",
"properties": {
"hour": {
"type": "integer",
"minimum": 0,
"maximum": 23
},
"sent": {
"type": "integer"
},
"opens": {
"type": "integer"
},
"clicks": {
"type": "integer"
},
"replies": {
"type": "integer"
}
}
},
"CampaignComparison": {
"type": "object",
"description": "Side-by-side performance for up to 10 campaigns over a date range.",
"required": [
"campaigns",
"period"
],
"properties": {
"campaigns": {
"type": "array",
"items": {
"$ref": "#/components/schemas/CampaignComparisonItem"
}
},
"period": {
"$ref": "#/components/schemas/DateRange"
}
}
},
"CampaignComparisonItem": {
"type": "object",
"properties": {
"campaign_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"status": {
"type": "string"
},
"emails_sent": {
"type": "integer"
},
"open_rate": {
"type": "number"
},
"click_rate": {
"type": "number"
},
"reply_rate": {
"type": "number"
},
"bounce_rate": {
"type": "number"
}
}
},
"AccountStatus": {
"type": "object",
"description": "Summary health and usage status of an email account.",
"required": [
"id",
"email",
"provider",
"status",
"health",
"daily_usage"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"provider": {
"type": "string"
},
"status": {
"type": "string"
},
"last_synced_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"health": {
"$ref": "#/components/schemas/AccountHealth"
},
"errors": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AccountError"
}
},
"daily_usage": {
"$ref": "#/components/schemas/AccountDailyUsage"
},
"in_campaign": {
"type": "boolean"
}
}
},
"AccountStatusDetail": {
"allOf": [
{
"$ref": "#/components/schemas/AccountStatus"
},
{
"type": "object",
"description": "warmup_status is present only when warmup has ever been enabled; warmup_health is present only when the mailbox is in a warmup pool.",
"properties": {
"warmup_status": {
"$ref": "#/components/schemas/WarmupStatus"
},
"warmup_health": {
"$ref": "#/components/schemas/WarmupHealth"
}
}
}
]
},
"AccountHealth": {
"type": "object",
"properties": {
"status": {
"type": "string",
"description": "For example healthy, warning, error."
},
"score": {
"type": "integer"
},
"issues": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"AccountError": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"error_code": {
"type": "string"
},
"severity": {
"type": "string"
},
"title": {
"type": "string"
},
"message": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"AccountDailyUsage": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"campaign_sent": {
"type": "integer"
},
"campaign_limit": {
"type": "integer"
},
"warmup_sent": {
"type": "integer"
},
"warmup_limit": {
"type": "integer"
}
}
},
"WarmupStatus": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"paused": {
"type": "boolean"
},
"started_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"current_volume": {
"type": "integer"
},
"target_volume": {
"type": "integer"
},
"max_volume": {
"type": "integer"
},
"reply_rate": {
"type": "number"
},
"days_active": {
"type": "integer"
}
}
},
"WarmupHealth": {
"type": "object",
"properties": {
"state": {
"type": "string",
"enum": [
"healthy",
"watch",
"throttled",
"quarantined",
"blocked"
]
},
"score": {
"type": "integer"
},
"spam_score": {
"type": "integer"
},
"evaluated_at": {
"type": "string",
"format": "date-time"
}
}
},
"AccountStatusList": {
"type": "object",
"description": "All of the caller's account statuses under a data envelope (no cursor).",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AccountStatus"
}
}
}
},
"UsageOverview": {
"type": "object",
"description": "Account, campaign, contact, and API usage counters for the caller.",
"required": [
"period"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"period": {
"type": "string",
"enum": [
"day",
"week",
"month"
]
},
"email_accounts": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"active": {
"type": "integer"
},
"in_warmup": {
"type": "integer"
},
"with_errors": {
"type": "integer"
}
}
},
"campaigns": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"active": {
"type": "integer"
},
"paused": {
"type": "integer"
},
"draft": {
"type": "integer"
},
"emails_sent": {
"type": "integer"
}
}
},
"contacts": {
"type": "object",
"properties": {
"total": {
"type": "integer"
},
"subscribed": {
"type": "integer"
},
"added_today": {
"type": "integer"
}
}
},
"api": {
"type": "object",
"properties": {
"total_calls": {
"type": "integer"
},
"daily_limit": {
"type": "integer"
},
"top_endpoints": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
"AuditLog": {
"type": "object",
"description": "One organization audit-trail entry. actor is null when the acting user has since been deleted; entity_id, changes, and metadata are omitted when empty.",
"required": [
"id",
"org_id",
"action",
"entity_type",
"action_date"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"org_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"actor": {
"$ref": "#/components/schemas/AuditActor"
},
"action_date": {
"type": "string",
"format": "date-time"
},
"action": {
"type": "string"
},
"entity_type": {
"type": "string"
},
"entity_id": {
"type": "string",
"format": "uuid"
},
"ip_address": {
"type": "string"
},
"user_agent": {
"type": "string"
},
"changes": {
"type": "object",
"additionalProperties": true,
"description": "Field-level change set; secret values are never recorded."
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"timestamp": {
"type": "string",
"format": "date-time"
}
}
},
"AuditActor": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"email": {
"type": "string"
}
}
},
"AuditLogList": {
"type": "object",
"description": "A page of audit logs with an opaque cursor.",
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AuditLog"
}
},
"pagination": {
"$ref": "#/components/schemas/Pagination"
}
}
},
"IntegrationCatalogEntry": {
"type": "object",
"description": "Static metadata for one provider the dashboard renders even when no connection exists.",
"required": [
"provider",
"name",
"auth_method",
"supports_push",
"configured"
],
"properties": {
"provider": {
"type": "string",
"description": "Provider id.",
"enum": [
"hubspot",
"salesforce",
"pipedrive",
"close",
"zapier",
"make",
"n8n",
"slack",
"discord",
"calendly",
"cal_com",
"google_sheets"
]
},
"name": {
"type": "string"
},
"tagline": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"crm",
"automation",
"notifications",
"meetings",
"data"
]
},
"docs_url": {
"type": "string"
},
"auth_method": {
"type": "string",
"enum": [
"oauth",
"api_key",
"webhook"
]
},
"badge_color": {
"type": "string"
},
"beta": {
"type": "boolean"
},
"webhook_hint": {
"type": "string"
},
"highlights": {
"type": "array",
"items": {
"type": "string"
}
},
"scopes": {
"type": "array",
"items": {
"type": "string"
},
"description": "OAuth scopes requested at authorize time."
},
"events": {
"type": "array",
"items": {
"type": "string"
},
"description": "Warmbly events this provider can react to."
},
"action_types": {
"type": "array",
"items": {
"type": "string"
},
"description": "Provider action identifiers with a real backend handler."
},
"supports_push": {
"type": "boolean",
"description": "Whether this provider can be the target of the synchronous push-contacts action."
},
"capability": {
"type": [
"object",
"null"
],
"additionalProperties": true,
"description": "Configurable-action descriptor the dashboard renders onboarding + field-mapping UI from."
},
"configured": {
"type": "boolean",
"description": "Whether the server has OAuth client credentials wired for this provider."
}
}
},
"IntegrationCatalogList": {
"type": "object",
"required": [
"catalog"
],
"properties": {
"catalog": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationCatalogEntry"
}
}
}
},
"IntegrationConnection": {
"type": "object",
"description": "One org's link to one provider. Secrets are never serialized.",
"required": [
"id",
"organization_id",
"provider",
"label",
"status",
"auth_method",
"sync_direction",
"health",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"provider": {
"type": "string"
},
"label": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"pending",
"authorizing",
"connected",
"degraded",
"reauth_required",
"disconnected"
]
},
"auth_method": {
"type": "string",
"enum": [
"oauth",
"api_key",
"webhook"
]
},
"display_fields": {
"type": "object",
"additionalProperties": true,
"description": "Non-secret display fields."
},
"config_capabilities": {
"type": "object",
"additionalProperties": true,
"description": "Per-connection onboarding/capability snapshot."
},
"sync_direction": {
"type": "string",
"enum": [
"push",
"pull",
"both"
]
},
"connected_by_user_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"external_account_id": {
"type": "string"
},
"external_account_name": {
"type": "string"
},
"granted_scopes": {
"type": "array",
"items": {
"type": "string"
}
},
"token_expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"health": {
"type": "string",
"enum": [
"unknown",
"healthy",
"degraded",
"down"
]
},
"health_detail": {
"type": [
"string",
"null"
]
},
"health_checked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_synced_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"last_error": {
"type": [
"string",
"null"
]
},
"last_error_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"inbound_webhook_url": {
"type": "string",
"description": "Returned only at create time for inbound providers (Calendly, Cal.com)."
}
}
},
"IntegrationConnectionList": {
"type": "object",
"required": [
"connections"
],
"properties": {
"connections": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationConnection"
}
}
}
},
"IntegrationConnectionDetail": {
"type": "object",
"description": "A connection plus its event subscriptions and recent sync runs (the detail drawer payload).",
"required": [
"connection",
"events",
"runs"
],
"properties": {
"connection": {
"$ref": "#/components/schemas/IntegrationConnection"
},
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationEventSubscription"
}
},
"runs": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationSyncRun"
}
}
}
},
"IntegrationConnectionCreate": {
"type": "object",
"required": [
"provider"
],
"properties": {
"provider": {
"type": "string",
"description": "A valid api_key/webhook provider id (e.g. close, discord). OAuth providers are rejected."
},
"label": {
"type": "string",
"description": "Friendly name shown on the connection card."
},
"config": {
"type": "object",
"additionalProperties": true,
"description": "Provider-specific config (e.g. the pasted API key or webhook URL)."
}
}
},
"IntegrationConnectionConfigUpdate": {
"type": "object",
"properties": {
"config_capabilities": {
"type": "object",
"additionalProperties": true,
"description": "Per-connection capability snapshot (picker selections, enabled use-cases)."
},
"sync_direction": {
"type": "string",
"enum": [
"push",
"pull",
"both"
]
}
}
},
"IntegrationEventSubscription": {
"type": "object",
"description": "Routes a Warmbly event to a provider (or native) action on a connection.",
"required": [
"id",
"connection_id",
"event_type",
"action",
"enabled",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"connection_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"event_type": {
"type": "string",
"description": "The Warmbly event to react to (e.g. email.replied)."
},
"action": {
"type": "string",
"description": "Provider action id (e.g. slack.notify, hubspot.upsert_contact) or native action (e.g. warmbly.add_tag, warmbly.label_email)."
},
"config": {
"type": "object",
"additionalProperties": true,
"description": "Action config (e.g. a Slack channel or message template)."
},
"enabled": {
"type": "boolean"
},
"use_case": {
"type": "string",
"description": "Discriminator describing what this automation is for (e.g. crm_sync, notify, custom)."
},
"automation_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Set when this subscription is one step of an Automation flow."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"IntegrationEventSubscriptionList": {
"type": "object",
"required": [
"events"
],
"properties": {
"events": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationEventSubscription"
}
}
}
},
"IntegrationEventSubscriptionCreate": {
"type": "object",
"required": [
"event_type",
"action"
],
"properties": {
"event_type": {
"type": "string",
"description": "The Warmbly event to react to (e.g. email.replied)."
},
"action": {
"type": "string",
"description": "Provider action id (e.g. slack.notify, hubspot.upsert_contact)."
},
"config": {
"type": "object",
"additionalProperties": true,
"description": "Action config (e.g. a Slack channel or message template)."
},
"enabled": {
"type": "boolean",
"description": "Defaults to true when omitted."
}
}
},
"IntegrationFieldMapping": {
"type": "object",
"description": "One Warmbly-field to provider-field mapping row.",
"required": [
"id",
"connection_id",
"object_name",
"warmbly_field",
"external_field",
"is_default",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"connection_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"subscription_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"direction": {
"type": "string",
"enum": [
"push",
"pull",
"both"
]
},
"object_name": {
"type": "string"
},
"warmbly_field": {
"type": "string"
},
"external_field": {
"type": "string"
},
"transform": {
"type": "string",
"description": "One of '' (none), none, static, uppercase, lowercase, trim."
},
"static_value": {
"type": "string"
},
"is_default": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
},
"IntegrationFieldMappingList": {
"type": "object",
"required": [
"mappings"
],
"properties": {
"mappings": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationFieldMapping"
}
}
}
},
"IntegrationFieldMappingReplace": {
"type": "object",
"required": [
"mappings"
],
"properties": {
"object": {
"type": "string",
"description": "The provider object the mappings apply to (e.g. contact)."
},
"mappings": {
"type": "array",
"description": "The full set of mappings to store (replaces any existing).",
"items": {
"type": "object",
"required": [
"external_field"
],
"properties": {
"external_field": {
"type": "string",
"description": "Destination field on the provider. Required for every mapping."
},
"warmbly_field": {
"type": "string",
"description": "Source Warmbly field. Required unless transform is 'static'."
},
"transform": {
"type": "string",
"description": "One of '' (none), none, static, uppercase, lowercase, trim."
},
"static_value": {
"type": "string",
"description": "Required when transform is 'static'."
}
}
}
}
}
},
"IntegrationSyncRun": {
"type": "object",
"description": "One observability record of work done against a connection.",
"required": [
"id",
"connection_id",
"kind",
"status",
"records_processed",
"started_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"connection_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"kind": {
"type": "string",
"description": "e.g. connect, refresh, dispatch, push."
},
"status": {
"type": "string",
"description": "e.g. success, error."
},
"detail": {
"type": "string"
},
"records_processed": {
"type": "integer"
},
"started_at": {
"type": "string",
"format": "date-time"
},
"finished_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"IntegrationSyncRunList": {
"type": "object",
"required": [
"runs"
],
"properties": {
"runs": {
"type": "array",
"items": {
"$ref": "#/components/schemas/IntegrationSyncRun"
}
}
}
},
"IntegrationWebhookSecret": {
"type": "object",
"required": [
"signing_secret",
"signature_header",
"scheme"
],
"properties": {
"signing_secret": {
"type": "string",
"description": "HMAC signing secret used to verify outbound webhook signatures."
},
"signature_header": {
"type": "string",
"description": "Header carrying the signature (X-Warmbly-Signature)."
},
"scheme": {
"type": "string",
"description": "Signature scheme description."
}
}
},
"IntegrationPushRequest": {
"type": "object",
"properties": {
"contact_ids": {
"type": "array",
"description": "Contact ids to push. Deduplicated server-side. At least 1, at most 500. Required unless all is set.",
"items": {
"type": "string",
"format": "uuid"
},
"minItems": 1,
"maxItems": 500
},
"all": {
"type": "boolean",
"description": "Resolve the selection from filters instead of contacts."
},
"filters": {
"allOf": [
{
"$ref": "#/components/schemas/ContactSearchRequest"
}
],
"description": "The search whose matches the action applies to. Required when all is true."
},
"exclude": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"maxItems": 50000,
"description": "Contact ids to drop from the resolved set. Ignored unless all is set."
}
},
"description": "Contacts to push. The resolved set is capped at 500 whichever form is used: the push calls the CRM once per contact inside the request.",
"oneOf": [
{
"required": [
"contact_ids"
],
"properties": {
"all": {
"enum": [
false
]
}
}
},
{
"required": [
"all",
"filters"
],
"properties": {
"all": {
"enum": [
true
]
}
}
}
]
},
"IntegrationPushResult": {
"type": "object",
"required": [
"provider",
"pushed",
"failed",
"results"
],
"properties": {
"provider": {
"type": "string"
},
"pushed": {
"type": "integer"
},
"failed": {
"type": "integer"
},
"results": {
"type": "array",
"items": {
"type": "object",
"required": [
"contact_id",
"ok"
],
"properties": {
"contact_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string"
},
"ok": {
"type": "boolean"
},
"error": {
"type": "string",
"description": "Present when ok is false."
}
}
}
}
}
},
"MeetingBooking": {
"type": "object",
"description": "One booked meeting from a connected scheduling provider (Calendly, Cal.com) or a manually logged meeting.",
"required": [
"id",
"source",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"source": {
"type": "string",
"description": "e.g. calendly, cal_com, manual."
},
"external_event_id": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"booked",
"rescheduled",
"canceled",
"completed",
"no_show"
]
},
"invitee_email": {
"type": "string"
},
"invitee_name": {
"type": "string"
},
"event_name": {
"type": "string"
},
"event_type": {
"type": "string"
},
"scheduled_for": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"end_time": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"join_url": {
"type": "string"
},
"location": {
"type": "string"
},
"cancel_url": {
"type": "string"
},
"reschedule_url": {
"type": "string"
},
"canceled_reason": {
"type": "string"
},
"contact_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"campaign_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"contact_name": {
"type": "string",
"description": "Joined for list display."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"MeetingBookingList": {
"type": "object",
"required": [
"bookings"
],
"properties": {
"bookings": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MeetingBooking"
}
}
}
},
"Automation": {
"type": "object",
"description": "A branching flow: when the trigger event fires, the executor walks the graph, evaluating condition nodes and running the action nodes on matched paths.",
"required": [
"id",
"organization_id",
"name",
"enabled",
"trigger_event",
"graph",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"enabled": {
"type": "boolean"
},
"trigger_event": {
"type": "string",
"description": "The event that fires the flow (e.g. email.replied)."
},
"filter": {
"type": "object",
"additionalProperties": true,
"description": "Optional automation-wide gate (e.g. intents / min_confidence) applied to every action."
},
"graph": {
"$ref": "#/components/schemas/AutomationGraph"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"AutomationList": {
"type": "object",
"required": [
"automations"
],
"properties": {
"automations": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Automation"
}
}
}
},
"AutomationWrite": {
"type": "object",
"description": "Create/update payload from the flow builder.",
"required": [
"name",
"trigger_event",
"graph"
],
"properties": {
"name": {
"type": "string",
"description": "Display name."
},
"enabled": {
"type": "boolean",
"description": "Whether the automation runs on matching events."
},
"trigger_event": {
"type": "string",
"description": "The event that fires the flow (e.g. email.replied)."
},
"filter": {
"type": "object",
"additionalProperties": true,
"description": "Optional automation-wide gate applied to every action."
},
"graph": {
"$ref": "#/components/schemas/AutomationGraph"
}
}
},
"AutomationGraph": {
"type": "object",
"description": "The editable flow: nodes plus the edges connecting them.",
"required": [
"nodes",
"edges"
],
"properties": {
"nodes": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationNode"
}
},
"edges": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationEdge"
}
}
}
},
"AutomationNode": {
"type": "object",
"description": "One node on the canvas.",
"required": [
"id",
"type",
"x",
"y"
],
"properties": {
"id": {
"type": "string",
"description": "Node id. The single trigger node uses id 'trigger'."
},
"type": {
"type": "string",
"enum": [
"trigger",
"condition",
"action"
],
"description": "Exactly one trigger node; condition nodes have true/false outgoing edges; action nodes run a handler."
},
"action": {
"type": "string",
"description": "Action node only: provider action (e.g. slack.notify) or native action (e.g. warmbly.add_tag, warmbly.label_email, warmbly.run_automation)."
},
"connection_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Action node only: the integration connection the action runs against. Omitted for native (warmbly.*) actions."
},
"config": {
"type": "object",
"additionalProperties": true,
"description": "Action node config."
},
"condition": {
"$ref": "#/components/schemas/AutomationCondition"
},
"x": {
"type": "number",
"description": "Canvas x coordinate."
},
"y": {
"type": "number",
"description": "Canvas y coordinate."
}
}
},
"AutomationEdge": {
"type": "object",
"required": [
"id",
"source",
"target"
],
"properties": {
"id": {
"type": "string"
},
"source": {
"type": "string"
},
"target": {
"type": "string"
},
"when": {
"type": "string",
"description": "'' for plain edges; 'true' / 'false' for the two outgoing edges of a condition node."
}
}
},
"AutomationCondition": {
"type": "object",
"description": "An IF test evaluated against the trigger event's data.",
"required": [
"field",
"operator"
],
"properties": {
"field": {
"type": "string",
"description": "Condition kind, e.g. 'field' or 'expression'."
},
"key": {
"type": "string",
"description": "For 'field' conditions, the event-data key to test."
},
"operator": {
"type": "string"
},
"value": {
"description": "Comparison value (any JSON type)."
},
"expression": {
"type": "string",
"description": "For 'expression' conditions, a Go-template predicate evaluated against the event data."
}
}
},
"AutomationDryRunRequest": {
"type": "object",
"description": "Optional. When omitted, the server builds a sample event from the trigger.",
"properties": {
"data": {
"type": "object",
"additionalProperties": true,
"description": "Sample event payload to evaluate the flow against."
}
}
},
"AutomationDryRunResponse": {
"type": "object",
"required": [
"trace",
"data"
],
"properties": {
"trace": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationNodeResult"
}
},
"data": {
"type": "object",
"additionalProperties": true,
"description": "The resolved event data the flow was evaluated against."
}
}
},
"AutomationRun": {
"type": "object",
"description": "One execution of an automation graph (per fired event or manual launch).",
"required": [
"id",
"automation_id",
"trigger_event",
"status",
"node_results",
"started_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"automation_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"trigger_event": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"running",
"success",
"error"
]
},
"node_results": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationNodeResult"
}
},
"error_detail": {
"type": "string"
},
"started_at": {
"type": "string",
"format": "date-time"
},
"finished_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"AutomationRunList": {
"type": "object",
"required": [
"runs"
],
"properties": {
"runs": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AutomationRun"
}
}
}
},
"AutomationNodeResult": {
"type": "object",
"description": "One node's outcome in a run (or a dry-run trace).",
"required": [
"node_id",
"type",
"status"
],
"properties": {
"node_id": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"trigger",
"condition",
"action"
]
},
"action": {
"type": "string",
"description": "Action nodes only."
},
"label": {
"type": "string",
"description": "Human summary (e.g. 'Slack · #sales')."
},
"status": {
"type": "string",
"enum": [
"success",
"error",
"skipped",
"branch_true",
"branch_false"
]
},
"error": {
"type": "string"
},
"preview": {
"type": "object",
"additionalProperties": true,
"description": "Dry-run only: what the action would send."
}
}
},
"Team": {
"type": "object",
"description": "A named, color-tagged grouping of an organization's members.",
"required": [
"id",
"organization_id",
"name",
"color",
"members",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"color": {
"type": "string",
"description": "Hex color for the chip (defaults to #94a3b8)."
},
"members": {
"type": "array",
"description": "The members that belong to this team. Always an array (never null).",
"items": {
"$ref": "#/components/schemas/TeamMember"
}
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"TeamMember": {
"type": "object",
"description": "One membership row of a team, with the user's email and name joined for display.",
"required": [
"user_id",
"email",
"name",
"added_at"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string",
"format": "email"
},
"name": {
"type": "string"
},
"added_at": {
"type": "string",
"format": "date-time"
}
}
},
"TeamCollection": {
"type": "object",
"description": "A bare collection of teams (not cursor-paginated).",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Team"
}
}
}
},
"TeamCreate": {
"type": "object",
"description": "Request body for creating a team.",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"color": {
"type": "string",
"description": "Hex color (defaults to #94a3b8)."
}
}
},
"TeamUpdate": {
"type": "object",
"description": "Partial-update body for a team. Omitted fields are left untouched.",
"minProperties": 1,
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255
},
"color": {
"type": "string",
"description": "Hex color."
}
}
},
"TeamAddMember": {
"type": "object",
"description": "Request body for adding an existing organization member to a team.",
"required": [
"user_id"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid",
"description": "The member's user id (must already belong to the organization)."
}
}
},
"Plan": {
"type": "object",
"description": "A public subscription plan.",
"required": [
"id",
"price",
"duration",
"public"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": [
"string",
"null"
]
},
"max_contacts": {
"type": "integer"
},
"daily_emails": {
"type": "integer"
},
"ai_generation": {
"type": "boolean"
},
"account_limit": {
"type": "integer"
},
"price": {
"type": "number",
"format": "float"
},
"discounted_price": {
"type": "number",
"format": "float"
},
"duration": {
"type": "string",
"enum": [
"month",
"year"
]
},
"savings": {
"type": "integer",
"description": "Percentage savings versus monthly (0-255)."
},
"public": {
"type": "boolean"
},
"stripe_price_id": {
"type": [
"string",
"null"
]
},
"stripe_price_id_yearly": {
"type": [
"string",
"null"
]
},
"stripe_product_id": {
"type": [
"string",
"null"
]
},
"dedicated_workers": {
"type": "integer"
},
"daily_campaign_limit": {
"type": [
"integer",
"null"
]
},
"max_campaigns": {
"type": [
"integer",
"null"
]
},
"max_active_campaigns": {
"type": [
"integer",
"null"
]
},
"max_team_members": {
"type": [
"integer",
"null"
]
},
"max_email_accounts": {
"type": [
"integer",
"null"
]
},
"monthly_credits": {
"type": "integer",
"description": "AI writing-assistant monthly credit grant for this plan."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"PlanList": {
"type": "object",
"description": "The list of public subscription plans.",
"required": [
"plans"
],
"properties": {
"plans": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Plan"
}
}
}
},
"TimezoneOption": {
"type": "object",
"description": "A supported timezone identifier and its display label.",
"required": [
"name",
"display_name"
],
"properties": {
"name": {
"type": "string",
"description": "IANA name, e.g. \"Europe/Budapest\"."
},
"display_name": {
"type": "string",
"description": "Human label, e.g. \"(UTC+02:00) Europe/Budapest\"."
}
}
},
"UpsertOutreachSettingsRequest": {
"type": "object",
"required": [
"settings"
],
"properties": {
"settings": {
"$ref": "#/components/schemas/AdvancedOutreachSettings"
}
}
},
"IngestDeliverabilityEventRequest": {
"type": "object",
"required": [
"event_type",
"recipient_email"
],
"properties": {
"event_type": {
"type": "string",
"enum": [
"bounce",
"complaint",
"unsubscribe",
"open",
"click",
"reply"
],
"description": "The deliverability signal type."
},
"recipient_email": {
"type": "string",
"format": "email",
"description": "The recipient address the event is about."
},
"campaign_id": {
"type": "string",
"format": "uuid",
"description": "Campaign the event is attributed to."
},
"task_id": {
"type": "string",
"format": "uuid",
"description": "Send task the event is attributed to."
},
"contact_id": {
"type": "string",
"format": "uuid",
"description": "Contact the event is attributed to."
},
"provider": {
"type": "string",
"description": "Source provider label (e.g. ses, postmark)."
},
"reason": {
"type": "string",
"description": "Human-readable reason or diagnostic text."
},
"idempotency_key": {
"type": "string",
"description": "De-duplicates retried events."
},
"metadata": {
"type": "object",
"additionalProperties": true,
"description": "Free-form JSON attached to the event."
}
}
},
"TaskDeadLetter": {
"type": "object",
"description": "A task that exhausted its retry budget and landed in the dead-letter queue.",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"description": "Dead-letter record ID (use this to replay)."
},
"task_id": {
"type": "string",
"format": "uuid",
"description": "The underlying task ID."
},
"task_type": {
"type": "string"
},
"payload": {
"type": "object",
"additionalProperties": true,
"description": "The original task payload."
},
"last_error": {
"type": "string"
},
"attempts": {
"type": "integer"
},
"max_attempts": {
"type": "integer"
},
"status": {
"type": "string",
"description": "e.g. pending, replayed."
},
"next_retry_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"replayed_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"task_id",
"task_type",
"status",
"attempts",
"max_attempts",
"created_at",
"updated_at"
]
},
"TaskDeadLetterList": {
"type": "object",
"description": "List of dead-letter records. Not cursor-paginated.",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TaskDeadLetter"
}
}
}
},
"ReplayDeadLetterResponse": {
"type": "object",
"required": [
"status"
],
"properties": {
"status": {
"type": "string",
"example": "replayed"
}
}
},
"WarmupRoutingRule": {
"type": "object",
"description": "A customer-defined preference applied during premium-pool partner selection.",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"priority": {
"type": "integer",
"description": "Evaluation order, ascending (lower runs first)."
},
"sender_match_type": {
"type": "string",
"enum": [
"any",
"domain",
"tld",
"provider"
]
},
"sender_match_value": {
"type": "string",
"description": "Lowercased/trimmed; empty when sender_match_type is any."
},
"recipient_match_type": {
"type": "string",
"enum": [
"any",
"domain",
"tld",
"provider"
]
},
"recipient_match_value": {
"type": "string",
"description": "Lowercased/trimmed; empty when recipient_match_type is any."
},
"weight": {
"type": "number",
"description": "Selection weight, >= 0."
},
"enabled": {
"type": "boolean"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"organization_id",
"name",
"priority",
"sender_match_type",
"recipient_match_type",
"weight",
"enabled",
"created_at",
"updated_at"
]
},
"WarmupRoutingRuleInput": {
"type": "object",
"description": "Create/update payload for a warmup routing rule. A match value is required unless its match type is `any`.",
"required": [
"name",
"sender_match_type",
"recipient_match_type"
],
"properties": {
"name": {
"type": "string",
"description": "Display name for the rule."
},
"priority": {
"type": "integer",
"description": "Evaluation order, ascending. Lower runs first."
},
"sender_match_type": {
"type": "string",
"enum": [
"any",
"domain",
"tld",
"provider"
]
},
"sender_match_value": {
"type": "string",
"description": "Required unless sender_match_type is any. Domain (acme.com), TLD (com), or provider bucket (google, microsoft, yahoo, apple, proton, zoho, custom)."
},
"recipient_match_type": {
"type": "string",
"enum": [
"any",
"domain",
"tld",
"provider"
]
},
"recipient_match_value": {
"type": "string",
"description": "Required unless recipient_match_type is any. Same value forms as the sender side."
},
"weight": {
"type": "number",
"minimum": 0,
"description": "Selection weight, must be >= 0."
},
"enabled": {
"type": "boolean",
"description": "Whether the rule is active."
}
}
},
"WarmupRoutingRuleList": {
"type": "object",
"description": "Warmup routing rules under a `rules` key (always an array, never null). Not cursor-paginated.",
"required": [
"rules"
],
"properties": {
"rules": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WarmupRoutingRule"
}
}
}
},
"ReplyTemplate": {
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"user_id": {
"type": "string",
"format": "uuid",
"description": "Owner (the user that created the template)."
},
"name": {
"type": "string"
},
"subject": {
"type": "string",
"description": "May contain {{.Key}} placeholders."
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
},
"position": {
"type": "integer",
"description": "1-indexed ordering within the org's list."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"required": [
"id",
"organization_id",
"user_id",
"name",
"position",
"created_at",
"updated_at"
]
},
"ReplyTemplateList": {
"type": "object",
"description": "Reply templates under a `data` key. Not cursor-paginated.",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ReplyTemplate"
}
}
}
},
"CreateReplyTemplate": {
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 255,
"description": "Template name."
},
"subject": {
"type": "string",
"description": "Subject line (may contain {{.Key}} placeholders)."
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
}
}
},
"UpdateReplyTemplate": {
"type": "object",
"description": "All fields optional; omitted fields are left unchanged.",
"properties": {
"name": {
"type": "string"
},
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
}
}
},
"ReorderReplyTemplates": {
"type": "object",
"required": [
"ids"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
},
"description": "Template IDs in their new order (1-indexed). IDs omitted are left untouched."
}
}
},
"RenderReplyTemplateRequest": {
"type": "object",
"properties": {
"variables": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"description": "Values substituted into {{.Key}} placeholders."
}
}
},
"RenderedReplyTemplate": {
"type": "object",
"required": [
"subject",
"body_html",
"body_plain"
],
"properties": {
"subject": {
"type": "string"
},
"body_html": {
"type": "string"
},
"body_plain": {
"type": "string"
}
}
},
"ScoreTemplateRequest": {
"type": "object",
"description": "Content to score. body_plain is preferred over body_html when present.",
"properties": {
"subject": {
"type": "string"
},
"body_html": {
"type": "string",
"description": "Used when body_plain is empty."
},
"body_plain": {
"type": "string",
"description": "Preferred over HTML when present."
}
}
},
"TemplateScoreSpan": {
"type": "object",
"description": "One exact fragment of the copy that triggered an issue.",
"required": [
"field",
"text"
],
"properties": {
"field": {
"type": "string",
"enum": [
"subject",
"body"
]
},
"text": {
"type": "string",
"description": "The fragment as it is written in the copy."
},
"line": {
"type": "integer",
"description": "1-based line within that field."
},
"excerpt": {
"type": "string",
"description": "The whole line, for context around the fragment."
}
}
},
"TemplateScoreIssue": {
"type": "object",
"required": [
"severity",
"code",
"message"
],
"properties": {
"severity": {
"type": "string",
"enum": [
"warn",
"high"
]
},
"code": {
"type": "string",
"description": "Stable issue code (e.g. too_many_links)."
},
"message": {
"type": "string"
},
"field": {
"type": "string",
"description": "Set when the issue lives in exactly one half of the template. Absent when it straddles both or describes the send as a whole.",
"enum": [
"subject",
"body"
]
},
"spans": {
"type": "array",
"description": "The exact fragments that caused the issue, in reading order. Capped at 8; the count that drives the deduction is taken before the cap.",
"items": {
"$ref": "#/components/schemas/TemplateScoreSpan"
}
},
"suggestion": {
"type": "string",
"description": "The fix, in one sentence."
}
}
},
"SpamFinding": {
"type": "object",
"description": "One located problem the AI analysis found. `text` is verified against the submitted copy before it is returned, so it is never a fragment the caller did not send.",
"required": [
"severity",
"issue"
],
"properties": {
"severity": {
"type": "string",
"enum": [
"high",
"warn",
"info"
]
},
"field": {
"type": "string",
"description": "Absent when the model labelled neither half and nothing in the finding could be anchored in the copy.",
"enum": [
"subject",
"body"
]
},
"text": {
"type": "string",
"description": "The fragment quoted from the copy. Absent when the finding is about the email as a whole."
},
"line": {
"type": "integer"
},
"excerpt": {
"type": "string"
},
"issue": {
"type": "string",
"description": "Why this fragment hurts deliverability or replies."
},
"suggestion": {
"type": "string",
"description": "What to write instead."
},
"category": {
"type": "string",
"enum": [
"trigger_word",
"tone",
"formatting",
"links",
"structure",
"authenticity"
]
}
}
},
"TemplateAnalysis": {
"type": "object",
"description": "AI spam analysis of a campaign template, with the rules-based pass alongside it.",
"required": [
"score",
"verdict",
"findings",
"rules",
"model"
],
"properties": {
"score": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Overall deliverability score (higher is safer), grounded on the rules pass."
},
"verdict": {
"type": "string",
"description": "One sentence on how the email will land."
},
"findings": {
"type": "array",
"description": "Located problems, most severe first.",
"items": {
"$ref": "#/components/schemas/SpamFinding"
}
},
"suggested_subject": {
"type": "string",
"description": "A rewritten subject, absent when the current one is fine."
},
"improvements": {
"type": "array",
"description": "Copy-level advice with no single fragment to quote.",
"items": {
"type": "string"
}
},
"rules": {
"$ref": "#/components/schemas/TemplateScoreResult"
},
"model": {
"type": "string"
},
"tokens_used": {
"type": "integer"
},
"credits_remaining": {
"type": "integer"
},
"credits_charged": {
"type": "integer"
}
}
},
"TemplateScoreResult": {
"type": "object",
"required": [
"score",
"issues"
],
"properties": {
"score": {
"type": "integer",
"minimum": 0,
"maximum": 100,
"description": "Advisory content-safety score (higher is safer)."
},
"issues": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TemplateScoreIssue"
}
}
}
},
"SuppressedRecipient": {
"type": "object",
"description": "One entry on the workspace suppression list. A domain entry keeps the bare host in `email` and matches every address at it.",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"email": {
"type": "string",
"description": "The address, or the bare domain when kind is domain."
},
"kind": {
"type": "string",
"enum": [
"email",
"domain"
]
},
"reason": {
"type": "string"
},
"source": {
"type": "string",
"enum": [
"bounce",
"complaint",
"unsubscribe",
"manual",
"import"
]
},
"campaign_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"expires_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"SuppressionListResult": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SuppressedRecipient"
}
},
"pagination": {
"type": "object",
"properties": {
"next_cursor": {
"type": "string",
"nullable": true
},
"has_more": {
"type": "boolean"
}
}
}
}
},
"AddSuppressionsRequest": {
"type": "object",
"required": [
"entries"
],
"properties": {
"entries": {
"type": "array",
"maxItems": 5000,
"items": {
"type": "object",
"required": [
"value"
],
"properties": {
"value": {
"type": "string",
"description": "An address, or a bare domain (with or without a leading @)."
},
"reason": {
"type": "string"
}
}
}
},
"reason": {
"type": "string",
"description": "Applied to every entry without its own reason."
}
}
},
"AddSuppressionsResult": {
"type": "object",
"properties": {
"added": {
"type": "integer"
},
"skipped": {
"type": "array",
"items": {
"type": "string"
},
"description": "Values that were neither a valid address nor a valid domain."
}
}
},
"ContactLinkClick": {
"type": "object",
"description": "The link behind an email_clicked event: where it went, the anchor text it was minted from, and the UTM parameters the destination carried.",
"required": [
"id",
"url"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"url": {
"type": "string"
},
"label": {
"type": "string",
"description": "Anchor text the link was minted from."
},
"utm_source": {
"type": "string"
},
"utm_medium": {
"type": "string"
},
"utm_campaign": {
"type": "string"
},
"utm_term": {
"type": "string"
},
"utm_content": {
"type": "string"
},
"user_agent": {
"type": "string"
}
}
},
"EngagementOrigin": {
"type": "object",
"description": "Where an open or click came from. Every field is omitted when unknown; the source address itself is never stored.",
"properties": {
"client": {
"type": "string",
"description": "Mail client or image proxy named by the user agent (Gmail, Apple Mail, Outlook)."
},
"device_type": {
"type": "string"
},
"os": {
"type": "string"
},
"browser": {
"type": "string"
},
"browser_version": {
"type": "string"
},
"country_code": {
"type": "string"
},
"region": {
"type": "string"
},
"city": {
"type": "string"
}
}
},
"WebsitePageHit": {
"type": "object",
"description": "A page view reported by the website tracking snippet and tied to the contact through an email-link ticket.",
"required": [
"id",
"visitor_id",
"session_key",
"occurred_at",
"url",
"path",
"title",
"referrer",
"referrer_domain",
"landing",
"utm_source",
"utm_medium",
"utm_campaign",
"utm_term",
"utm_content",
"device_type",
"os",
"browser",
"browser_version",
"device_brand",
"language",
"timezone",
"screen_width",
"screen_height",
"country_code",
"region",
"city"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"visitor_id": {
"type": "string",
"format": "uuid"
},
"session_key": {
"type": "string"
},
"occurred_at": {
"type": "string",
"format": "date-time"
},
"url": {
"type": "string"
},
"path": {
"type": "string"
},
"title": {
"type": "string"
},
"referrer": {
"type": "string"
},
"referrer_domain": {
"type": "string"
},
"landing": {
"type": "boolean",
"description": "True for the first view of a session."
},
"utm_source": {
"type": "string"
},
"utm_medium": {
"type": "string"
},
"utm_campaign": {
"type": "string"
},
"utm_term": {
"type": "string"
},
"utm_content": {
"type": "string"
},
"device_type": {
"type": "string"
},
"os": {
"type": "string"
},
"browser": {
"type": "string"
},
"browser_version": {
"type": "string"
},
"device_brand": {
"type": "string"
},
"language": {
"type": "string"
},
"timezone": {
"type": "string"
},
"screen_width": {
"type": "integer"
},
"screen_height": {
"type": "integer"
},
"country_code": {
"type": "string"
},
"region": {
"type": "string"
},
"city": {
"type": "string"
}
}
},
"Label": {
"type": "object",
"description": "One entry in a workspace label registry (a folder, tag or category). Registries belong to the organization, so every member sees and can edit the same set.",
"required": [
"id",
"title",
"color",
"position",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"title": {
"type": "string",
"description": "1 to 50 characters."
},
"color": {
"type": "string",
"description": "Hex colour, `#rrggbb`."
},
"position": {
"type": "integer",
"description": "0-based order within its own registry."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"CreateLabel": {
"type": "object",
"required": [
"title"
],
"properties": {
"title": {
"type": "string",
"description": "1 to 50 characters."
},
"color": {
"type": "string",
"description": "Hex colour, `#rrggbb`. Omit to let the server pick from its palette."
}
}
},
"UpdateLabel": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "1 to 50 characters."
},
"color": {
"type": "string",
"description": "Hex colour, `#rrggbb`."
}
}
},
"MoveLabel": {
"type": "object",
"required": [
"position"
],
"properties": {
"position": {
"type": "integer",
"description": "New 0-based position within the registry."
}
}
},
"LabelOrder": {
"type": "object",
"description": "One label's place in the registry after a move.",
"required": [
"id",
"position"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"position": {
"type": "integer"
}
}
}
}
}
}