mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 00:01:14 +00:00
27732 lines
735 KiB
JSON
27732 lines
735 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Warmbly API",
|
|
"version": "1.0.0",
|
|
"description": "The Warmbly API lets you drive mailboxes, campaigns, contacts, the unibox, CRM, and more programmatically. Authenticate with an API key as a Bearer token. All paths are relative to the versioned base URL.",
|
|
"contact": {
|
|
"name": "Warmbly",
|
|
"url": "https://docs.warmbly.com"
|
|
},
|
|
"license": {
|
|
"name": "Proprietary",
|
|
"url": "https://warmbly.com"
|
|
}
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "https://api.warmbly.com/v1",
|
|
"description": "Production (v1)"
|
|
}
|
|
],
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"tags": [
|
|
{
|
|
"name": "auth",
|
|
"description": "Authentication: login, registration, password reset, 2FA, and sessions."
|
|
},
|
|
{
|
|
"name": "mailboxes",
|
|
"description": "Connected sending mailboxes and their warmup lifecycle."
|
|
},
|
|
{
|
|
"name": "campaigns",
|
|
"description": "Cold outreach campaigns, steps, and A/B variants."
|
|
},
|
|
{
|
|
"name": "contacts",
|
|
"description": "Contacts and their tags."
|
|
},
|
|
{
|
|
"name": "unibox",
|
|
"description": "Unified inbox: threads, replies, and labels."
|
|
},
|
|
{
|
|
"name": "crm",
|
|
"description": "Deals, tasks, notes, and pipelines."
|
|
},
|
|
{
|
|
"name": "api-keys",
|
|
"description": "API key management and usage logs."
|
|
},
|
|
{
|
|
"name": "webhooks",
|
|
"description": "Outbound webhook endpoints and deliveries."
|
|
},
|
|
{
|
|
"name": "analytics",
|
|
"description": "Campaign and deliverability analytics."
|
|
},
|
|
{
|
|
"name": "integrations",
|
|
"description": "Third-party connections and automations."
|
|
},
|
|
{
|
|
"name": "account-org",
|
|
"description": "Account, organization, and plan reference data."
|
|
},
|
|
{
|
|
"name": "deliverability-ops",
|
|
"description": "Deliverability event ingest, suppression, and seed placement."
|
|
}
|
|
],
|
|
"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 <addr@example.com>`) is accepted and unwrapped. Scope `READ_CONTACTS`.",
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "email",
|
|
"in": "query",
|
|
"required": true,
|
|
"description": "The email address to resolve.",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The resolved contact, or null.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ContactLookupResult"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Missing or malformed email.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid API key.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Rate limited.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/contacts/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"contacts"
|
|
],
|
|
"operationId": "contacts_get",
|
|
"summary": "Get a contact",
|
|
"description": "Returns the hydrated contact 360 payload: the contact plus an engagement summary and, when present, suppression state. Scope `READ_CONTACTS`.",
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "The hydrated contact.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ContactDetail"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Invalid contact ID.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid API key.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Contact not found.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Rate limited.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"tags": [
|
|
"contacts"
|
|
],
|
|
"operationId": "contacts_update",
|
|
"summary": "Update a contact",
|
|
"description": "Partially updates a single contact; only the fields present change. Category lists can be set wholesale or adjusted with diff-style add/remove. Scope `WRITE_CONTACTS`.",
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
{
|
|
"$ref": "#/components/parameters/IdempotencyKey"
|
|
}
|
|
],
|
|
"requestBody": {
|
|
"required": true,
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ContactUpdate"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"description": "The updated contact.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Contact"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Invalid contact ID or body.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid API key.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Contact not found.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Rate limited.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"contacts"
|
|
],
|
|
"operationId": "contacts_delete",
|
|
"summary": "Delete a contact",
|
|
"description": "Deletes a single contact. Scope `WRITE_CONTACTS`.",
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
{
|
|
"$ref": "#/components/parameters/IdempotencyKey"
|
|
}
|
|
],
|
|
"responses": {
|
|
"204": {
|
|
"description": "Contact deleted."
|
|
},
|
|
"400": {
|
|
"description": "Invalid contact ID.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid API key.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "API key lacks WRITE_CONTACTS or caller lacks manage_contacts.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Contact not found.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Rate limited.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/contacts/{id}/emails": {
|
|
"get": {
|
|
"tags": [
|
|
"contacts"
|
|
],
|
|
"operationId": "contacts_emails_list",
|
|
"summary": "List emails sent to a contact",
|
|
"description": "One row per email sent (or attempted) to the contact, newest first. Keyset paginated on (created_at, task_id); pass both before_at and before_id together. Scope `READ_CONTACTS`.",
|
|
"security": [
|
|
{
|
|
"bearerAuth": []
|
|
}
|
|
],
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
},
|
|
{
|
|
"name": "limit",
|
|
"in": "query",
|
|
"required": false,
|
|
"description": "Page size, 1 to 200 (default 50).",
|
|
"schema": {
|
|
"type": "integer",
|
|
"minimum": 1,
|
|
"maximum": 200,
|
|
"default": 50
|
|
}
|
|
},
|
|
{
|
|
"name": "before_at",
|
|
"in": "query",
|
|
"required": false,
|
|
"description": "created_at of the last row from the previous page (RFC 3339 nano).",
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
{
|
|
"name": "before_id",
|
|
"in": "query",
|
|
"required": false,
|
|
"description": "task_id of the last row from the previous page.",
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Sent emails.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ContactSentEmailList"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Invalid contact ID or limit.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Missing or invalid API key.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "API key lacks READ_CONTACTS or caller lacks view_contacts.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Contact not found.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Rate limited.",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Error"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/contacts/{id}/timeline": {
|
|
"get": {
|
|
"tags": [
|
|
"contacts"
|
|
],
|
|
"operationId": "contacts_timeline_list",
|
|
"summary": "List a contact's timeline",
|
|
"description": "Merged activity feed: sends, opens, clicks, replies, bounces, deliverability/suppression events, notes, 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:<key>). Empty uses defaults."
|
|
},
|
|
"filename": {
|
|
"type": "string",
|
|
"description": "Filename without extension. Sanitized server-side; empty falls back to contacts-<YYYY-MM-DD>."
|
|
}
|
|
}
|
|
},
|
|
"ContactImportColumnMapping": {
|
|
"type": "object",
|
|
"description": "Maps a source column index to a target contact field.",
|
|
"required": [
|
|
"index",
|
|
"target"
|
|
],
|
|
"properties": {
|
|
"index": {
|
|
"type": "integer",
|
|
"description": "Zero-based source column index."
|
|
},
|
|
"target": {
|
|
"type": "string",
|
|
"enum": [
|
|
"ignore",
|
|
"email",
|
|
"first_name",
|
|
"last_name",
|
|
"company",
|
|
"phone",
|
|
"subscribed",
|
|
"categories"
|
|
],
|
|
"description": "Target field, or a custom:<key> string for a custom field."
|
|
},
|
|
"custom_key": {
|
|
"type": "string",
|
|
"description": "Custom-field key when target is custom:<key>."
|
|
}
|
|
}
|
|
},
|
|
"ContactImportPreview": {
|
|
"type": "object",
|
|
"description": "Detected columns and a sample for building a column mapping.",
|
|
"required": [
|
|
"filename",
|
|
"format",
|
|
"total_rows",
|
|
"columns",
|
|
"has_header",
|
|
"sample_rows",
|
|
"suggested_mapping"
|
|
],
|
|
"properties": {
|
|
"filename": {
|
|
"type": "string"
|
|
},
|
|
"format": {
|
|
"type": "string",
|
|
"description": "csv or xlsx."
|
|
},
|
|
"total_rows": {
|
|
"type": "integer"
|
|
},
|
|
"columns": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"has_header": {
|
|
"type": "boolean"
|
|
},
|
|
"sample_rows": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"description": "Capped at 20 rows."
|
|
},
|
|
"suggested_mapping": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/ContactImportColumnMapping"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ContactImportRowError": {
|
|
"type": "object",
|
|
"description": "A single failed import row.",
|
|
"required": [
|
|
"line",
|
|
"reason"
|
|
],
|
|
"properties": {
|
|
"line": {
|
|
"type": "integer"
|
|
},
|
|
"email": {
|
|
"type": "string"
|
|
},
|
|
"values": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"reason": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"ContactImportResult": {
|
|
"type": "object",
|
|
"description": "Per-row results of an import commit.",
|
|
"required": [
|
|
"total",
|
|
"imported",
|
|
"updated",
|
|
"skipped",
|
|
"failed",
|
|
"started_at",
|
|
"ended_at"
|
|
],
|
|
"properties": {
|
|
"total": {
|
|
"type": "integer"
|
|
},
|
|
"imported": {
|
|
"type": "integer"
|
|
},
|
|
"updated": {
|
|
"type": "integer"
|
|
},
|
|
"skipped": {
|
|
"type": "integer"
|
|
},
|
|
"failed": {
|
|
"type": "integer"
|
|
},
|
|
"started_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"ended_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"errors": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/ContactImportRowError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"ContactLookupResult": {
|
|
"type": "object",
|
|
"description": "Resolved contact for a sender address; contact is null when nothing matches.",
|
|
"required": [
|
|
"contact"
|
|
],
|
|
"properties": {
|
|
"contact": {
|
|
"allOf": [
|
|
{
|
|
"$ref": "#/components/schemas/Contact"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"ContactSentEmail": {
|
|
"type": "object",
|
|
"description": "One email sent (or attempted) to a contact.",
|
|
"required": [
|
|
"task_id",
|
|
"status",
|
|
"message_id",
|
|
"subject",
|
|
"sent_at"
|
|
],
|
|
"properties": {
|
|
"task_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"message_id": {
|
|
"type": "string"
|
|
},
|
|
"subject": {
|
|
"type": "string"
|
|
},
|
|
"sent_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"email_account_id": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "uuid"
|
|
},
|
|
"email_account_email": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"email_account_name": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"campaign_id": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "uuid"
|
|
},
|
|
"campaign_name": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"step_id": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "uuid"
|
|
},
|
|
"step_name": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
]
|
|
},
|
|
"opened_at": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "date-time"
|
|
},
|
|
"clicked_at": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "date-time"
|
|
},
|
|
"replied_at": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "date-time"
|
|
},
|
|
"bounced_at": {
|
|
"type": [
|
|
"string",
|
|
"null"
|
|
],
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"ContactSentEmailList": {
|
|
"type": "object",
|
|
"description": "A page of emails sent to a contact.",
|
|
"required": [
|
|
"data",
|
|
"pagination"
|
|
],
|
|
"properties": {
|
|
"data": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/ContactSentEmail"
|
|
}
|
|
},
|
|
"pagination": {
|
|
"$ref": "#/components/schemas/Pagination"
|
|
}
|
|
}
|
|
},
|
|
"ContactTimelineEvent": {
|
|
"type": "object",
|
|
"description": "One entry in a contact's merged activity feed. Fields not relevant to the event type are omitted.",
|
|
"required": [
|
|
"type",
|
|
"at"
|
|
],
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"enum": [
|
|
"email_sent",
|
|
"email_opened",
|
|
"email_clicked",
|
|
"email_replied",
|
|
"email_bounced",
|
|
"reply_received",
|
|
"deliverability",
|
|
"suppressed",
|
|
"note",
|
|
"meeting_booked",
|
|
"meeting_rescheduled",
|
|
"meeting_canceled"
|
|
]
|
|
},
|
|
"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=<unix>,v1=<hex>`, where `v1 = hex(hmac_sha256(secret, \"<t>.\" + rawBody))`. Other headers: `X-Warmbly-Event` (event type), `X-Warmbly-Event-Id` (the event id for dedupe), `User-Agent: Warmbly-Webhooks/1.0`.",
|
|
"required": [
|
|
"id",
|
|
"event_type",
|
|
"organization_id",
|
|
"created_at",
|
|
"data"
|
|
],
|
|
"properties": {
|
|
"id": {
|
|
"type": "string",
|
|
"format": "uuid",
|
|
"description": "Unique event id, stable across retries. Matches `X-Warmbly-Event-Id`."
|
|
},
|
|
"event_type": {
|
|
"$ref": "#/components/schemas/WebhookEventType"
|
|
},
|
|
"organization_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time",
|
|
"description": "RFC 3339 UTC timestamp of when the event was dispatched."
|
|
},
|
|
"data": {
|
|
"type": "object",
|
|
"additionalProperties": true,
|
|
"description": "Event-specific payload. Shape depends on `event_type`."
|
|
}
|
|
}
|
|
},
|
|
"DashboardAnalytics": {
|
|
"type": "object",
|
|
"description": "Org-wide dashboard overview.",
|
|
"required": [
|
|
"period",
|
|
"overall_stats",
|
|
"recent_activity",
|
|
"top_campaigns",
|
|
"account_health",
|
|
"daily_trend"
|
|
],
|
|
"properties": {
|
|
"period": {
|
|
"type": "string",
|
|
"enum": [
|
|
"7d",
|
|
"30d",
|
|
"90d"
|
|
]
|
|
},
|
|
"overall_stats": {
|
|
"$ref": "#/components/schemas/OverallStats"
|
|
},
|
|
"recent_activity": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/RecentActivity"
|
|
}
|
|
},
|
|
"top_campaigns": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/TopCampaign"
|
|
}
|
|
},
|
|
"account_health": {
|
|
"$ref": "#/components/schemas/AccountHealthSummary"
|
|
},
|
|
"daily_trend": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/DailyTrendPoint"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"OverallStats": {
|
|
"type": "object",
|
|
"properties": {
|
|
"total_emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"total_opens": {
|
|
"type": "integer"
|
|
},
|
|
"machine_opens": {
|
|
"type": "integer"
|
|
},
|
|
"total_clicks": {
|
|
"type": "integer"
|
|
},
|
|
"total_replies": {
|
|
"type": "integer"
|
|
},
|
|
"total_bounces": {
|
|
"type": "integer"
|
|
},
|
|
"open_rate": {
|
|
"type": "number"
|
|
},
|
|
"click_rate": {
|
|
"type": "number"
|
|
},
|
|
"reply_rate": {
|
|
"type": "number"
|
|
},
|
|
"bounce_rate": {
|
|
"type": "number"
|
|
},
|
|
"active_campaigns": {
|
|
"type": "integer"
|
|
},
|
|
"active_accounts": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"RecentActivity": {
|
|
"type": "object",
|
|
"properties": {
|
|
"type": {
|
|
"type": "string",
|
|
"description": "Activity type, for example replied, opened, clicked."
|
|
},
|
|
"campaign_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"campaign_name": {
|
|
"type": "string"
|
|
},
|
|
"contact_email": {
|
|
"type": "string"
|
|
},
|
|
"contact_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"timestamp": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"TopCampaign": {
|
|
"type": "object",
|
|
"properties": {
|
|
"campaign_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"open_rate": {
|
|
"type": "number"
|
|
},
|
|
"click_rate": {
|
|
"type": "number"
|
|
},
|
|
"reply_rate": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"AccountHealthSummary": {
|
|
"type": "object",
|
|
"properties": {
|
|
"total_accounts": {
|
|
"type": "integer"
|
|
},
|
|
"healthy_accounts": {
|
|
"type": "integer"
|
|
},
|
|
"warning_accounts": {
|
|
"type": "integer"
|
|
},
|
|
"error_accounts": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"DailyTrendPoint": {
|
|
"type": "object",
|
|
"properties": {
|
|
"date": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"sent": {
|
|
"type": "integer"
|
|
},
|
|
"opens": {
|
|
"type": "integer"
|
|
},
|
|
"clicks": {
|
|
"type": "integer"
|
|
},
|
|
"replies": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"DeliverabilityDashboard": {
|
|
"type": "object",
|
|
"description": "Deliverability posture over a window. spam_placement_rate and inbox_placement_rate are omitted when there are no seed samples.",
|
|
"required": [
|
|
"from",
|
|
"to",
|
|
"band"
|
|
],
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"events_total": {
|
|
"type": "integer"
|
|
},
|
|
"bounce_count": {
|
|
"type": "integer"
|
|
},
|
|
"complaint_count": {
|
|
"type": "integer"
|
|
},
|
|
"unsubscribe_count": {
|
|
"type": "integer"
|
|
},
|
|
"reply_count": {
|
|
"type": "integer"
|
|
},
|
|
"open_count": {
|
|
"type": "integer"
|
|
},
|
|
"click_count": {
|
|
"type": "integer"
|
|
},
|
|
"suppressed_recipients": {
|
|
"type": "integer"
|
|
},
|
|
"dlq_pending": {
|
|
"type": "integer"
|
|
},
|
|
"intent_positive": {
|
|
"type": "integer"
|
|
},
|
|
"intent_negative": {
|
|
"type": "integer"
|
|
},
|
|
"intent_out_of_office": {
|
|
"type": "integer"
|
|
},
|
|
"intent_question": {
|
|
"type": "integer"
|
|
},
|
|
"intent_neutral": {
|
|
"type": "integer"
|
|
},
|
|
"emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"bounce_rate": {
|
|
"type": "number"
|
|
},
|
|
"complaint_rate": {
|
|
"type": "number"
|
|
},
|
|
"open_rate": {
|
|
"type": "number"
|
|
},
|
|
"click_rate": {
|
|
"type": "number"
|
|
},
|
|
"reply_rate": {
|
|
"type": "number"
|
|
},
|
|
"spam_placement_rate": {
|
|
"type": "number",
|
|
"description": "Omitted when there are no seed samples in the window."
|
|
},
|
|
"inbox_placement_rate": {
|
|
"type": "number",
|
|
"description": "Omitted when there are no seed samples in the window."
|
|
},
|
|
"placement_samples": {
|
|
"type": "integer"
|
|
},
|
|
"band": {
|
|
"type": "string",
|
|
"description": "Overall health band.",
|
|
"enum": [
|
|
"healthy",
|
|
"watch",
|
|
"throttled",
|
|
"quarantined",
|
|
"blocked"
|
|
]
|
|
},
|
|
"timeseries": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/DeliverabilityDayPoint"
|
|
}
|
|
},
|
|
"by_mailbox": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/DeliverabilityMailbox"
|
|
}
|
|
},
|
|
"by_campaign": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/DeliverabilityCampaign"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"DeliverabilityDayPoint": {
|
|
"type": "object",
|
|
"properties": {
|
|
"date": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"sent": {
|
|
"type": "integer"
|
|
},
|
|
"bounces": {
|
|
"type": "integer"
|
|
},
|
|
"complaints": {
|
|
"type": "integer"
|
|
},
|
|
"opens": {
|
|
"type": "integer"
|
|
},
|
|
"clicks": {
|
|
"type": "integer"
|
|
},
|
|
"replies": {
|
|
"type": "integer"
|
|
},
|
|
"unsubscribes": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"DeliverabilityMailbox": {
|
|
"type": "object",
|
|
"properties": {
|
|
"email_account_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"email": {
|
|
"type": "string"
|
|
},
|
|
"sent": {
|
|
"type": "integer"
|
|
},
|
|
"bounces": {
|
|
"type": "integer"
|
|
},
|
|
"complaints": {
|
|
"type": "integer"
|
|
},
|
|
"bounce_rate": {
|
|
"type": "number"
|
|
},
|
|
"complaint_rate": {
|
|
"type": "number"
|
|
},
|
|
"band": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"DeliverabilityCampaign": {
|
|
"type": "object",
|
|
"properties": {
|
|
"campaign_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"sent": {
|
|
"type": "integer"
|
|
},
|
|
"bounces": {
|
|
"type": "integer"
|
|
},
|
|
"complaints": {
|
|
"type": "integer"
|
|
},
|
|
"bounce_rate": {
|
|
"type": "number"
|
|
},
|
|
"complaint_rate": {
|
|
"type": "number"
|
|
},
|
|
"band": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"WarmupAnalytics": {
|
|
"type": "object",
|
|
"description": "Warmup send and reply statistics over a date range. email_account_id is the zero UUID when no email_id filter is supplied.",
|
|
"required": [
|
|
"email_account_id",
|
|
"date_range",
|
|
"summary",
|
|
"daily_stats"
|
|
],
|
|
"properties": {
|
|
"email_account_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"email": {
|
|
"type": "string"
|
|
},
|
|
"date_range": {
|
|
"$ref": "#/components/schemas/DateRange"
|
|
},
|
|
"summary": {
|
|
"$ref": "#/components/schemas/WarmupSummary"
|
|
},
|
|
"daily_stats": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/WarmupDayPoint"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"WarmupSummary": {
|
|
"type": "object",
|
|
"properties": {
|
|
"total_sent": {
|
|
"type": "integer"
|
|
},
|
|
"total_replied": {
|
|
"type": "integer"
|
|
},
|
|
"average_daily": {
|
|
"type": "number"
|
|
},
|
|
"reply_rate": {
|
|
"type": "number"
|
|
},
|
|
"target_progress": {
|
|
"type": "number"
|
|
},
|
|
"days_active": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"WarmupDayPoint": {
|
|
"type": "object",
|
|
"properties": {
|
|
"date": {
|
|
"type": "string",
|
|
"format": "date"
|
|
},
|
|
"emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"emails_replied": {
|
|
"type": "integer"
|
|
},
|
|
"target_volume": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"DateRange": {
|
|
"type": "object",
|
|
"properties": {
|
|
"from": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"to": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
},
|
|
"CampaignAnalytics": {
|
|
"type": "object",
|
|
"description": "A single campaign's performance summary plus per-step stats.",
|
|
"required": [
|
|
"campaign_id",
|
|
"name",
|
|
"status",
|
|
"summary",
|
|
"steps"
|
|
],
|
|
"properties": {
|
|
"campaign_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"date_range": {
|
|
"$ref": "#/components/schemas/DateRange"
|
|
},
|
|
"summary": {
|
|
"$ref": "#/components/schemas/CampaignAnalyticsSummary"
|
|
},
|
|
"steps": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/CampaignStepStats"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"CampaignAnalyticsSummary": {
|
|
"type": "object",
|
|
"description": "machine_opens is the subset of unique_opens from automated fetchers; human opens are unique_opens minus machine_opens.",
|
|
"properties": {
|
|
"total_contacts": {
|
|
"type": "integer"
|
|
},
|
|
"emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"emails_pending": {
|
|
"type": "integer"
|
|
},
|
|
"unique_opens": {
|
|
"type": "integer"
|
|
},
|
|
"machine_opens": {
|
|
"type": "integer"
|
|
},
|
|
"unique_clicks": {
|
|
"type": "integer"
|
|
},
|
|
"replies": {
|
|
"type": "integer"
|
|
},
|
|
"bounces": {
|
|
"type": "integer"
|
|
},
|
|
"unsubscribes": {
|
|
"type": "integer"
|
|
},
|
|
"open_rate": {
|
|
"type": "number"
|
|
},
|
|
"click_rate": {
|
|
"type": "number"
|
|
},
|
|
"reply_rate": {
|
|
"type": "number"
|
|
},
|
|
"bounce_rate": {
|
|
"type": "number"
|
|
}
|
|
}
|
|
},
|
|
"CampaignStepStats": {
|
|
"type": "object",
|
|
"properties": {
|
|
"step_id": {
|
|
"type": "string",
|
|
"format": "uuid"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"position": {
|
|
"type": "integer"
|
|
},
|
|
"emails_sent": {
|
|
"type": "integer"
|
|
},
|
|
"opens": {
|
|
"type": "integer"
|
|
},
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|