{ "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." } ], "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/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." } } } } } }, "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.", "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 up to 1000 contacts: 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": "No contacts provided or more than 1000.", "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 up to 1000 contacts by ID. Scope `BULK_CONTACTS`.", "security": [ { "bearerAuth": [] } ], "parameters": [ { "$ref": "#/components/parameters/IdempotencyKey" } ], "requestBody": { "required": true, "description": "A JSON array of contact ID strings (1 to 1000).", "content": { "application/json": { "schema": { "type": "array", "minItems": 1, "maxItems": 1000, "items": { "type": "string", "format": "uuid" } } } } }, "responses": { "204": { "description": "Contacts deleted." }, "400": { "description": "Empty array or more than 1000 IDs.", "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 `) 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, and meeting bookings. Requires a selected organization. Paginate via the `before` timestamp. 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", "in": "query", "required": false, "description": "The `at` timestamp of the oldest event from the previous page (RFC 3339 nano).", "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "Timeline events with a has_more flag.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactTimelineResult" } } } }, "400": { "description": "Invalid contact ID, 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`.", "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": "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 (your 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/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}/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": "Bad request (no/too many/invalid contact ids).", "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/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" } } } } } } } }, "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" }, "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" }, "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" ] }, "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", "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", "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" }, "sequences": { "type": "array", "items": { "$ref": "#/components/schemas/CampaignStepCreate" }, "description": "Initial sequence steps in order." }, "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", "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": "Minutes to wait after this step before the next." }, "position": { "type": "integer" }, "kind": { "type": "string", "enum": [ "email", "action", "wait" ] }, "conditions": { "type": "object", "description": "Branching tree ({branches: [...]}).", "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": "Minutes to wait after this step (spacing model; no standalone wait node for email steps)." }, "conditions": { "type": "object", "description": "Branching tree ({branches: [...]}). Send {} or empty branches to clear branching.", "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", "filename", "created_at" ], "properties": { "id": { "type": "string", "format": "uuid" }, "campaign_id": { "type": "string", "format": "uuid" }, "step_id": { "type": [ "string", "null" ], "format": "uuid" }, "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" } } } } }, "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": { "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." } } }, "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", "replied", "bounced", "unsubscribed" ] }, "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." }, "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, e.g. first_name, campaign_count." }, "reverse": { "type": "boolean", "description": "Descending when true." } } }, "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)." } } }, "ContactBulkUpdateRequest": { "type": "object", "description": "One set of edits applied across many contacts.", "required": [ "contacts" ], "properties": { "contacts": { "type": "array", "minItems": 1, "maxItems": 1000, "items": { "type": "string", "format": "uuid" }, "description": "Contact IDs to edit (1 to 1000)." }, "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:). Empty uses defaults." }, "filename": { "type": "string", "description": "Filename without extension. Sanitized server-side; empty falls back to contacts-." } } }, "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: string for a custom field." }, "custom_key": { "type": "string", "description": "Custom-field key when target is custom:." } } }, "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" ] }, "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." } } }, "ContactTimelineResult": { "type": "object", "description": "A page of timeline events. Paginate via has_more and the `before` query param; this list does not use a cursor envelope.", "required": [ "data", "has_more" ], "properties": { "data": { "type": "array", "items": { "$ref": "#/components/schemas/ContactTimelineEvent" } }, "has_more": { "type": "boolean" } } }, "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" }, "body_html": { "type": "string" } } }, "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." }, "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" } } }, "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.", "required": [ "email_ids" ], "properties": { "email_ids": { "type": "array", "items": { "type": "string", "format": "uuid" }, "maxItems": 500, "description": "Message UUIDs to update (max 500)." }, "seen": { "type": "boolean", "description": "`true` marks as read, `false` marks as unread." } } }, "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" ] } } }, "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=,v1=`, where `v1 = hex(hmac_sha256(secret, \".\" + 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" }, "clicks": { "type": "integer" }, "replies": { "type": "integer" }, "bounces": { "type": "integer" } } }, "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", "required": [ "contact_ids" ], "properties": { "contact_ids": { "type": "array", "description": "Contact ids to push. Deduplicated server-side. At least 1, at most 500.", "items": { "type": "string", "format": "uuid" }, "minItems": 1, "maxItems": 500 } } }, "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." } } }, "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" } } }, "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" } } } } } } }