{
  "openapi": "3.1.0",
  "info": {
    "title": "WarmySender Public API",
    "version": "1.0.0",
    "description": "The WarmySender Public REST API for cold emailing, email warmup, LinkedIn outreach, and multichannel campaigns.\n\n**Authentication.** Every request (except `GET /me` and this spec) requires a Bearer API key in the `Authorization` header: `Authorization: Bearer wsk_...`. Create keys in your workspace settings and grant each key only the scopes it needs.\n\n**Response envelope.** Successful responses wrap their payload in a `data` field. List endpoints add a `pagination` object (`{ has_more, next_cursor }`) for cursor-based paging, and most responses include a `meta.request_id`. Errors return `{ error: { code, message, ... } }` with the matching HTTP status. (`GET /me` is the one endpoint not wrapped in `data`.)\n\n**Rate limit.** 60 requests per minute, per workspace. Connection-test endpoints have an additional, stricter limit. When throttled you receive `429` with a `Retry-After` header.\n\n**Idempotency.** Write endpoints that create or mutate resources accept (and some require) a unique `Idempotency-Key` header so retries never duplicate work. Reusing a key returns the original result; reusing it with a different body returns `409`.\n\n**Webhooks.** WarmySender also delivers outbound webhooks (reply received, bounce, open, click, LinkedIn invite accepted, and more). Register endpoints with the Webhooks API; the available event types and their payloads are listed under the `x-webhook-events` extension of this document.",
    "contact": {
      "name": "WarmySender Support",
      "email": "support@warmysender.com",
      "url": "https://warmysender.com/documentation"
    }
  },
  "servers": [
    {
      "url": "https://warmysender.com/api/v1"
    }
  ],
  "tags": [
    {
      "name": "Identity"
    },
    {
      "name": "Mailboxes"
    },
    {
      "name": "Warmup"
    },
    {
      "name": "Jobs"
    },
    {
      "name": "Prospects"
    },
    {
      "name": "Suppressions"
    },
    {
      "name": "Campaigns"
    },
    {
      "name": "Enrollments"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "LinkedIn"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key (wsk_...)"
      }
    }
  },
  "paths": {
    "/me": {
      "get": {
        "operationId": "identity-me",
        "summary": "Get the authenticated API key + workspace",
        "description": "Returns the API key and workspace that the Bearer token belongs to, including the key's granted scopes. Useful for verifying a key and discovering its permissions. This is the one endpoint whose response is NOT wrapped in the standard data envelope.\n\nNo scope required — any valid API key works.",
        "tags": [
          "Identity"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "apiKey": {
                    "id": "key_8f1c2a",
                    "name": "Production integration",
                    "scopes": [
                      "mailboxes:read",
                      "mailboxes:write",
                      "warmup:read"
                    ]
                  },
                  "workspace": {
                    "id": "ws_4b9d10"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes": {
      "get": {
        "operationId": "mailboxes-list",
        "summary": "List mailboxes",
        "description": "Returns connected mailboxes, newest first, with cursor pagination. Soft-deleted mailboxes are excluded unless you filter by status=deleted.\n\nRequired scope: `mailboxes:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Exact-match filter on your external_id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email_address",
            "in": "query",
            "required": false,
            "description": "Case-insensitive substring match on the email address.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by status.",
            "schema": {
              "type": "string",
              "enum": [
                "created",
                "testing",
                "connected",
                "error",
                "deleted"
              ]
            }
          },
          {
            "name": "warmup_enabled",
            "in": "query",
            "required": false,
            "description": "Filter by warmup on/off.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                      "external_id": "crm-contact-8841",
                      "email_address": "sender@yourdomain.com",
                      "display_name": "Jordan Lee",
                      "status": "connected",
                      "health_status": "ok",
                      "health_reasons": null,
                      "warmup_enabled": true,
                      "warmup_type": "normal",
                      "warmup_progress": 62,
                      "sending_enabled": true,
                      "daily_send_limit": 50,
                      "last_tested_at": "2026-06-10T08:31:00.000Z",
                      "last_test_error": null,
                      "signature": null,
                      "created_at": "2026-06-06T10:43:01.357Z",
                      "updated_at": "2026-06-10T08:31:05.220Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "mailboxes-create",
        "summary": "Create a mailbox",
        "description": "Adds a mailbox and runs an asynchronous connection test (status moves created → testing → connected or error). If the email matches a previously soft-deleted mailbox, that mailbox is restored instead and the response is 200 with its preserved warmup history (otherwise 201).\n\nRequired scope: `mailboxes:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.\n\nSend a unique Idempotency-Key header so retries never create duplicates.\n\nConnection test runs in the background — poll GET /mailboxes/{id} until status is \"connected\".",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email_address": {
                    "type": "string",
                    "format": "email",
                    "description": "The mailbox email address."
                  },
                  "smtp_host": {
                    "type": "string",
                    "description": "SMTP server hostname, e.g. smtp.gmail.com."
                  },
                  "smtp_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "default": 587,
                    "description": "SMTP port. One of 25, 465, 587. Defaults to 587."
                  },
                  "smtp_username": {
                    "type": "string",
                    "description": "SMTP login (usually the email address)."
                  },
                  "smtp_password": {
                    "type": "string",
                    "format": "password",
                    "description": "SMTP password or app password."
                  },
                  "imap_host": {
                    "type": "string",
                    "description": "IMAP server hostname, e.g. imap.gmail.com."
                  },
                  "imap_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "default": 993,
                    "description": "IMAP port. One of 143, 993. Defaults to 993."
                  },
                  "imap_username": {
                    "type": "string",
                    "description": "IMAP login (usually the email address)."
                  },
                  "imap_password": {
                    "type": "string",
                    "format": "password",
                    "description": "IMAP password or app password."
                  },
                  "external_id": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Your own reference id for this mailbox (unique per workspace)."
                  },
                  "display_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Display name shown on outgoing mail."
                  },
                  "sending_enabled": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether the mailbox may send. Defaults to true."
                  },
                  "daily_send_limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000,
                    "default": 50,
                    "description": "Max sends per day. Defaults to 50."
                  },
                  "auto_enable_warmup": {
                    "type": "boolean",
                    "default": false,
                    "description": "Enable warmup automatically once the connection test passes."
                  }
                },
                "required": [
                  "email_address",
                  "smtp_host",
                  "smtp_username",
                  "smtp_password",
                  "imap_host",
                  "imap_username",
                  "imap_password"
                ]
              },
              "example": {
                "email_address": "sender@yourdomain.com",
                "smtp_host": "smtp.gmail.com",
                "smtp_port": 587,
                "smtp_username": "sender@yourdomain.com",
                "smtp_password": "app-password",
                "imap_host": "imap.gmail.com",
                "imap_port": 993,
                "imap_username": "sender@yourdomain.com",
                "imap_password": "app-password",
                "external_id": "crm-contact-8841",
                "auto_enable_warmup": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "external_id": "crm-contact-8841",
                    "email_address": "sender@yourdomain.com",
                    "display_name": "Jordan Lee",
                    "status": "testing",
                    "health_status": "ok",
                    "health_reasons": null,
                    "warmup_enabled": true,
                    "warmup_type": "normal",
                    "warmup_progress": 0,
                    "sending_enabled": true,
                    "daily_send_limit": 50,
                    "last_tested_at": null,
                    "last_test_error": null,
                    "signature": null,
                    "created_at": "2026-06-06T10:43:01.357Z",
                    "updated_at": "2026-06-10T08:31:05.220Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6",
                    "idempotency_key": "550e8400-e29b-41d4-a716-446655440000"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`mailbox_limit_exceeded` — At or above your plan's mailbox limit.; `insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "mailbox_limit_exceeded",
                    "message": "At or above your plan's mailbox limit."
                  }
                }
              }
            }
          },
          "409": {
            "description": "`duplicate_email` — An active mailbox already uses this email.; `duplicate_external_id` — The external_id is already in use.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "duplicate_email",
                    "message": "An active mailbox already uses this email."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`ssrf_blocked` — A host resolved to a private/internal IP.; `invalid_port` — A port outside the allowed list (25/465/587/143/993).",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "ssrf_blocked",
                    "message": "A host resolved to a private/internal IP."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes/{id}": {
      "get": {
        "operationId": "mailboxes-get",
        "summary": "Get a mailbox",
        "description": "Fetch a single mailbox by id. Poll this after create/restore until status becomes \"connected\".\n\nRequired scope: `mailboxes:read`.",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "external_id": "crm-contact-8841",
                    "email_address": "sender@yourdomain.com",
                    "display_name": "Jordan Lee",
                    "status": "connected",
                    "health_status": "ok",
                    "health_reasons": null,
                    "warmup_enabled": true,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "sending_enabled": true,
                    "daily_send_limit": 50,
                    "last_tested_at": "2026-06-10T08:31:00.000Z",
                    "last_test_error": null,
                    "signature": null,
                    "created_at": "2026-06-06T10:43:01.357Z",
                    "updated_at": "2026-06-10T08:31:05.220Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — No mailbox with that id in your workspace.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "No mailbox with that id in your workspace."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "mailboxes-update",
        "summary": "Update a mailbox",
        "description": "Partial update — only the fields you send change. Changing SMTP/IMAP credentials re-runs the connection test. Set external_id or signature to null to clear them.\n\nRequired scope: `mailboxes:write`.",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "type": "string",
                    "maxLength": 255,
                    "description": "Display name."
                  },
                  "smtp_host": {
                    "type": "string",
                    "description": "SMTP host."
                  },
                  "smtp_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "description": "SMTP port (25/465/587)."
                  },
                  "smtp_username": {
                    "type": "string",
                    "description": "SMTP login."
                  },
                  "smtp_password": {
                    "type": "string",
                    "format": "password",
                    "description": "SMTP password."
                  },
                  "imap_host": {
                    "type": "string",
                    "description": "IMAP host."
                  },
                  "imap_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "description": "IMAP port (143/993)."
                  },
                  "imap_username": {
                    "type": "string",
                    "description": "IMAP login."
                  },
                  "imap_password": {
                    "type": "string",
                    "format": "password",
                    "description": "IMAP password."
                  },
                  "sending_enabled": {
                    "type": "boolean",
                    "description": "Allow sending."
                  },
                  "daily_send_limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 1000,
                    "description": "Daily send cap."
                  },
                  "external_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 255,
                    "description": "Your reference id, or null to clear."
                  },
                  "signature": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 65536,
                    "description": "HTML/text signature, or null to clear."
                  }
                }
              },
              "example": {
                "display_name": "Jordan Lee",
                "daily_send_limit": 80
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "external_id": "crm-contact-8841",
                    "email_address": "sender@yourdomain.com",
                    "display_name": "Jordan Lee",
                    "status": "connected",
                    "health_status": "ok",
                    "health_reasons": null,
                    "warmup_enabled": true,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "sending_enabled": true,
                    "daily_send_limit": 80,
                    "last_tested_at": "2026-06-10T08:31:00.000Z",
                    "last_test_error": null,
                    "signature": null,
                    "created_at": "2026-06-06T10:43:01.357Z",
                    "updated_at": "2026-06-10T08:31:05.220Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Mailbox not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Mailbox not found."
                  }
                }
              }
            }
          },
          "409": {
            "description": "`duplicate_external_id` — The new external_id is already in use.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "duplicate_external_id",
                    "message": "The new external_id is already in use."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`ssrf_blocked` — A host resolved to a private/internal IP.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "ssrf_blocked",
                    "message": "A host resolved to a private/internal IP."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "mailboxes-delete",
        "summary": "Delete (soft) a mailbox",
        "description": "Soft-deletes the mailbox: it stops sending and warmup immediately but its history is preserved so it can be restored. Returns 200 with the mailbox object (status \"deleted\") — not 204.\n\nRequired scope: `mailboxes:write`.",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "external_id": "crm-contact-8841",
                    "email_address": "sender@yourdomain.com",
                    "display_name": "Jordan Lee",
                    "status": "deleted",
                    "health_status": "ok",
                    "health_reasons": null,
                    "warmup_enabled": false,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "sending_enabled": true,
                    "daily_send_limit": 50,
                    "last_tested_at": "2026-06-10T08:31:00.000Z",
                    "last_test_error": null,
                    "signature": null,
                    "created_at": "2026-06-06T10:43:01.357Z",
                    "updated_at": "2026-06-10T08:31:05.220Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Mailbox not found (or already deleted).",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Mailbox not found (or already deleted)."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes/test": {
      "post": {
        "operationId": "mailboxes-test",
        "summary": "Test credentials (no save)",
        "description": "Synchronously tests SMTP + IMAP credentials WITHOUT creating a mailbox. Rate limited.\n\nRequired scope: `mailboxes:write`.\n\nSubject to a stricter per-endpoint connection-test rate limit (in addition to the workspace-wide 60 req/min limit).\n\nport_corrected and original_port appear only when an SMTP port fallback succeeded.",
        "tags": [
          "Mailboxes"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email_address": {
                    "type": "string",
                    "format": "email",
                    "description": "The mailbox email address."
                  },
                  "smtp_host": {
                    "type": "string",
                    "description": "SMTP server hostname, e.g. smtp.gmail.com."
                  },
                  "smtp_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "default": 587,
                    "description": "SMTP port. One of 25, 465, 587. Defaults to 587."
                  },
                  "smtp_username": {
                    "type": "string",
                    "description": "SMTP login (usually the email address)."
                  },
                  "smtp_password": {
                    "type": "string",
                    "format": "password",
                    "description": "SMTP password or app password."
                  },
                  "imap_host": {
                    "type": "string",
                    "description": "IMAP server hostname, e.g. imap.gmail.com."
                  },
                  "imap_port": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 65535,
                    "default": 993,
                    "description": "IMAP port. One of 143, 993. Defaults to 993."
                  },
                  "imap_username": {
                    "type": "string",
                    "description": "IMAP login (usually the email address)."
                  },
                  "imap_password": {
                    "type": "string",
                    "format": "password",
                    "description": "IMAP password or app password."
                  }
                },
                "required": [
                  "email_address",
                  "smtp_host",
                  "smtp_username",
                  "smtp_password",
                  "imap_host",
                  "imap_username",
                  "imap_password"
                ]
              },
              "example": {
                "email_address": "sender@yourdomain.com",
                "smtp_host": "smtp.gmail.com",
                "smtp_port": 587,
                "smtp_username": "sender@yourdomain.com",
                "smtp_password": "app-password",
                "imap_host": "imap.gmail.com",
                "imap_port": 993,
                "imap_username": "sender@yourdomain.com",
                "imap_password": "app-password"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "smtp_ok": true,
                    "imap_ok": true
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`ssrf_blocked` — A host resolved to a private/internal IP.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "ssrf_blocked",
                    "message": "A host resolved to a private/internal IP."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes/{id}/restore": {
      "post": {
        "operationId": "mailboxes-restore",
        "summary": "Restore a deleted mailbox",
        "description": "Brings a soft-deleted mailbox back with its warmup history intact and re-runs the connection test (status returns to \"created\" → \"connected\"). Warmup starts disabled; enable it once connected. Blocked if an active mailbox already uses the same email.\n\nRequired scope: `mailboxes:write`.\n\nPoll GET /mailboxes/{id} until status is \"connected\".",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "external_id": "crm-contact-8841",
                    "email_address": "sender@yourdomain.com",
                    "display_name": "Jordan Lee",
                    "status": "created",
                    "health_status": "ok",
                    "health_reasons": null,
                    "warmup_enabled": false,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "sending_enabled": true,
                    "daily_send_limit": 50,
                    "last_tested_at": "2026-06-10T08:31:00.000Z",
                    "last_test_error": null,
                    "signature": null,
                    "created_at": "2026-06-06T10:43:01.357Z",
                    "updated_at": "2026-06-10T08:31:05.220Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — No soft-deleted mailbox with that id.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "No soft-deleted mailbox with that id."
                  }
                }
              }
            }
          },
          "409": {
            "description": "`duplicate_email` — An active mailbox already uses this email.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "duplicate_email",
                    "message": "An active mailbox already uses this email."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/mailboxes/{id}/test": {
      "post": {
        "operationId": "mailboxes-retest",
        "summary": "Re-test a mailbox connection",
        "description": "Re-runs the SMTP + IMAP connection test against the stored credentials and updates the mailbox status. Rate limited.\n\nRequired scope: `mailboxes:write`.\n\nSubject to a stricter per-endpoint connection-test rate limit (in addition to the workspace-wide 60 req/min limit).",
        "tags": [
          "Mailboxes"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "mailbox": {
                      "id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                      "external_id": "crm-contact-8841",
                      "email_address": "sender@yourdomain.com",
                      "display_name": "Jordan Lee",
                      "status": "connected",
                      "health_status": "ok",
                      "health_reasons": null,
                      "warmup_enabled": true,
                      "warmup_type": "normal",
                      "warmup_progress": 62,
                      "sending_enabled": true,
                      "daily_send_limit": 50,
                      "last_tested_at": "2026-06-10T08:31:00.000Z",
                      "last_test_error": null,
                      "signature": null,
                      "created_at": "2026-06-06T10:43:01.357Z",
                      "updated_at": "2026-06-10T08:31:05.220Z"
                    },
                    "test_result": {
                      "smtp_ok": true,
                      "imap_ok": true
                    }
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Mailbox not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Mailbox not found."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`ssrf_blocked` — A host resolved to a private/internal IP.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "ssrf_blocked",
                    "message": "A host resolved to a private/internal IP."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/warmup/stats": {
      "get": {
        "operationId": "warmup-stats-list",
        "summary": "List warmup stats",
        "description": "Per-mailbox warmup health: progress, today's volume, inbox/spam rate, reputation. Cursor paginated.\n\nRequired scope: `warmup:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "Warmup"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "mailbox_id",
            "in": "query",
            "required": false,
            "description": "One mailbox id, or comma-separated ids (up to 100), to filter.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "mailbox_id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                      "email_address": "sender@yourdomain.com",
                      "warmup_enabled": true,
                      "warmup_type": "normal",
                      "warmup_progress": 62,
                      "warmup_target_daily_volume": 50,
                      "effective_daily_limit": 50,
                      "effective_limit_reason": null,
                      "sent_today": 18,
                      "received_today": 17,
                      "reputation_score": 96,
                      "inbox_rate": 98,
                      "spam_rate": 1,
                      "last_sent_at": "2026-06-10T09:12:00.000Z",
                      "health_status": "ok",
                      "health_reasons": null
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/warmup/stats/{mailboxId}": {
      "get": {
        "operationId": "warmup-stats-get",
        "summary": "Get warmup stats for one mailbox",
        "description": "Warmup health for a single mailbox.\n\nRequired scope: `warmup:read`.",
        "tags": [
          "Warmup"
        ],
        "parameters": [
          {
            "name": "mailboxId",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "mailbox_id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "email_address": "sender@yourdomain.com",
                    "warmup_enabled": true,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "warmup_target_daily_volume": 50,
                    "effective_daily_limit": 50,
                    "effective_limit_reason": null,
                    "sent_today": 18,
                    "received_today": 17,
                    "reputation_score": 96,
                    "inbox_rate": 98,
                    "spam_rate": 1,
                    "last_sent_at": "2026-06-10T09:12:00.000Z",
                    "health_status": "ok",
                    "health_reasons": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Mailbox not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Mailbox not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/warmup/settings/{mailboxId}": {
      "patch": {
        "operationId": "warmup-settings-update",
        "summary": "Update warmup settings",
        "description": "Enable/disable warmup, switch strategy, or set the target daily volume for one mailbox. Enabling requires the mailbox status to be \"connected\".\n\nRequired scope: `warmup:write`.",
        "tags": [
          "Warmup"
        ],
        "parameters": [
          {
            "name": "mailboxId",
            "in": "path",
            "required": true,
            "description": "Mailbox id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "warmup_enabled": {
                    "type": "boolean",
                    "description": "Turn warmup on or off. Enabling requires the mailbox status to be \"connected\"."
                  },
                  "warmup_type": {
                    "type": "string",
                    "enum": [
                      "new_domain",
                      "new_mailbox",
                      "dormant",
                      "maintenance",
                      "recovery",
                      "aggressive",
                      "normal",
                      "conservative"
                    ],
                    "description": "Warmup strategy. Controls ramp speed and target."
                  },
                  "warmup_target_daily_volume": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Target warmup emails per day once fully ramped."
                  }
                }
              },
              "example": {
                "warmup_enabled": true,
                "warmup_type": "normal",
                "warmup_target_daily_volume": 50
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "mailbox_id": "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                    "email_address": "sender@yourdomain.com",
                    "warmup_enabled": true,
                    "warmup_type": "normal",
                    "warmup_progress": 62,
                    "warmup_target_daily_volume": 50,
                    "effective_daily_limit": 50,
                    "effective_limit_reason": null,
                    "sent_today": 18,
                    "received_today": 17,
                    "reputation_score": 96,
                    "inbox_rate": 98,
                    "spam_rate": 1,
                    "last_sent_at": "2026-06-10T09:12:00.000Z",
                    "health_status": "ok",
                    "health_reasons": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Mailbox not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Mailbox not found."
                  }
                }
              }
            }
          },
          "422": {
            "description": "`mailbox_not_connected` — Tried to enable warmup on a mailbox that is not connected.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "mailbox_not_connected",
                    "message": "Tried to enable warmup on a mailbox that is not connected."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/warmup/bulk-update": {
      "post": {
        "operationId": "warmup-bulk-update",
        "summary": "Bulk-update warmup settings (async)",
        "description": "Applies the same warmup changes to many mailboxes at once. Returns 202 with a job id immediately — poll GET /jobs/{id} for progress. Mailboxes that can't be enabled (not connected) are recorded as per-item errors on the job.\n\nRequired scope: `warmup:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Warmup"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mailbox_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 500,
                    "description": "Mailbox ids to update (1–500)."
                  },
                  "updates": {
                    "type": "object",
                    "description": "A warmup settings object — same fields as Update warmup settings (warmup_enabled, warmup_type, warmup_target_daily_volume). At least one field required."
                  }
                },
                "required": [
                  "mailbox_ids",
                  "updates"
                ]
              },
              "example": {
                "mailbox_ids": [
                  "5bd50e20-6b75-4429-9a5a-4a09b46e945a",
                  "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
                ],
                "updates": {
                  "warmup_enabled": true,
                  "warmup_type": "normal"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "job_id": "job_7d2f1a",
                    "status": "processing",
                    "total_items": 2
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6",
                    "idempotency_key": "550e8400-e29b-41d4-a716-446655440000"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation or no update fields given.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation or no update fields given."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`mailboxes_not_found` — One or more mailbox ids don't exist (details.missing_mailbox_ids).",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "mailboxes_not_found",
                    "message": "One or more mailbox ids don't exist (details.missing_mailbox_ids)."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/jobs/{id}": {
      "get": {
        "operationId": "jobs-get",
        "summary": "Get job status",
        "description": "Status and progress of an asynchronous job (e.g. a warmup bulk-update). Per-item failures are listed in errors.\n\nRequired scope: `jobs:read`.",
        "tags": [
          "Jobs"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Job id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "job_7d2f1a",
                    "type": "bulk_warmup_update",
                    "status": "completed",
                    "total_items": 2,
                    "processed_items": 2,
                    "failed_items": 0,
                    "errors": [],
                    "created_at": "2026-06-10T12:00:00.000Z",
                    "completed_at": "2026-06-10T12:00:04.000Z"
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Job not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Job not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/prospects": {
      "get": {
        "operationId": "prospects-list",
        "summary": "List prospects",
        "description": "Returns prospects in your workspace with cursor pagination.\n\nRequired scope: `prospects:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "Prospects"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter",
            "in": "query",
            "required": false,
            "description": "Repeatable metadata filter, formatted field:op:value (e.g. company:eq:Acme, custom:region:eq:US, email:exists). Fields: email, firstName, lastName, company, role, country, city, industry, globalStatus, tags, or custom:<key>. Ops: eq, neq, contains, exists. Unknown/invalid filters are ignored and echoed back in filters_ignored.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "f3c4a2d1-9b7e-4c2a-8f10-2b6d5e8a1c44",
                      "email": "jane@acme.com",
                      "firstName": "Jane",
                      "lastName": "Doe",
                      "company": "Acme Inc",
                      "role": "CTO",
                      "phone": null,
                      "globalStatus": "active",
                      "linkedinUrl": "https://www.linkedin.com/in/janedoe",
                      "instagramUsername": "janedoe",
                      "customFields": {
                        "plan": "enterprise"
                      },
                      "createdAt": "2026-06-09T14:02:00.000Z",
                      "updatedAt": "2026-06-09T14:02:00.000Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "prospects-create",
        "summary": "Create a prospect",
        "description": "Creates a prospect. Provide at least one of email, linkedinUrl, or instagramUsername — a prospect with no email address is still created and can be enrolled in LinkedIn or Instagram campaigns. If one with the same email already exists it is merged and returned with alreadyExisted=true (HTTP 200); a brand-new prospect returns 201. Pass listId to drop the prospect into one of your lists; if a running campaign is linked to that list the prospect is auto-enrolled (continuous enrollment) — ideal for a website signup or popup form. Pass enrollInCampaignId instead to enroll into one specific campaign in the same call.\n\nRequired scope: `prospects:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.\n\nThe prospect is always saved even if list attach or enrollment can't complete — the outcome is reported in the list / enrollment fields rather than failing the call.\n\nlistId echoes back the list you passed (or null), and list is { attached: true, enrolledCampaigns: <n> } on success, or { attached: false, error: \"list_not_found\", message: ... } if the list ID was wrong.\n\nenrolledCampaigns counts the running campaigns linked to the list that the prospect was just folded into.",
        "tags": [
          "Prospects"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Prospect email (unique per workspace). Optional — provide email, linkedinUrl, or instagramUsername."
                  },
                  "firstName": {
                    "type": "string",
                    "description": "First name."
                  },
                  "lastName": {
                    "type": "string",
                    "description": "Last name."
                  },
                  "company": {
                    "type": "string",
                    "description": "Company."
                  },
                  "role": {
                    "type": "string",
                    "description": "Job title / role."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone number."
                  },
                  "linkedinUrl": {
                    "type": "string",
                    "format": "uri",
                    "description": "LinkedIn profile URL. Use for a LinkedIn-only prospect with no email."
                  },
                  "instagramUsername": {
                    "type": "string",
                    "description": "Instagram handle (with or without the leading @, or a full instagram.com profile URL). Use for an Instagram-only prospect with no email."
                  },
                  "customFields": {
                    "type": "object",
                    "description": "Arbitrary key/value pairs for personalization."
                  },
                  "listId": {
                    "type": "string",
                    "description": "Add the created/updated prospect to this list. When a running campaign is linked to the list, the prospect is auto-enrolled into it (continuous enrollment). Find the list ID on the Lists page."
                  },
                  "enroll": {
                    "type": "boolean",
                    "default": true,
                    "description": "When listId is set and a running campaign is linked to that list, auto-enroll the prospect into it. Set false to add to the list only, without enrolling. Defaults to true. Ignored when listId is omitted."
                  },
                  "enrollInCampaignId": {
                    "type": "string",
                    "description": "Enroll the created/updated prospect into this specific campaign in the same call (bypasses lists). Requires the enrollments:write scope. Suppressed prospects are skipped."
                  }
                }
              },
              "example": {
                "email": "lead@example.com",
                "firstName": "Sam",
                "listId": "list_9f3a2b",
                "enroll": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`list_not_found` — listId did not match a list in your workspace. The prospect is still saved; see list.error in the response body.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "list_not_found",
                    "message": "listId did not match a list in your workspace. The prospect is still saved; see list.error in the response body."
                  }
                }
              }
            }
          },
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "f3c4a2d1-9b7e-4c2a-8f10-2b6d5e8a1c44",
                    "email": "jane@acme.com",
                    "firstName": "Jane",
                    "lastName": "Doe",
                    "company": "Acme Inc",
                    "role": "CTO",
                    "phone": null,
                    "globalStatus": "active",
                    "linkedinUrl": "https://www.linkedin.com/in/janedoe",
                    "instagramUsername": "janedoe",
                    "customFields": {
                      "plan": "enterprise"
                    },
                    "createdAt": "2026-06-09T14:02:00.000Z",
                    "updatedAt": "2026-06-09T14:02:00.000Z"
                  },
                  "alreadyExisted": false,
                  "listId": "list_9f3a2b",
                  "list": {
                    "attached": true,
                    "enrolledCampaigns": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation, or none of email, linkedinUrl, or instagramUsername was provided.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation, or none of email, linkedinUrl, or instagramUsername was provided."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`prospect_limit_reached` — Workspace prospect limit reached.; `insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "prospect_limit_reached",
                    "message": "Workspace prospect limit reached."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/prospects/{id}": {
      "patch": {
        "operationId": "prospects-update",
        "summary": "Update a prospect",
        "description": "Partial update of a prospect. linkedinUrl and instagramUsername may be set or cleared (null). globalStatus can be changed (e.g. to mark unsubscribed).\n\nRequired scope: `prospects:write`.",
        "tags": [
          "Prospects"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Prospect id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "firstName": {
                    "type": "string",
                    "description": "First name."
                  },
                  "lastName": {
                    "type": "string",
                    "description": "Last name."
                  },
                  "company": {
                    "type": "string",
                    "description": "Company."
                  },
                  "role": {
                    "type": "string",
                    "description": "Role."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone."
                  },
                  "linkedinUrl": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "uri",
                    "description": "LinkedIn URL, or null to clear."
                  },
                  "instagramUsername": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Instagram handle (with or without the leading @, or a full instagram.com profile URL), or null to clear."
                  },
                  "customFields": {
                    "type": "object",
                    "description": "Custom fields (replaces existing)."
                  },
                  "globalStatus": {
                    "type": "string",
                    "enum": [
                      "active",
                      "bounced",
                      "invalid",
                      "unsubscribed",
                      "dnc",
                      "suppressed"
                    ],
                    "description": "Lifecycle status."
                  }
                }
              },
              "example": {
                "role": "VP Engineering",
                "globalStatus": "active"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "f3c4a2d1-9b7e-4c2a-8f10-2b6d5e8a1c44",
                    "email": "jane@acme.com",
                    "firstName": "Jane",
                    "lastName": "Doe",
                    "company": "Acme Inc",
                    "role": "VP Engineering",
                    "phone": null,
                    "globalStatus": "active",
                    "linkedinUrl": "https://www.linkedin.com/in/janedoe",
                    "instagramUsername": "janedoe",
                    "customFields": {
                      "plan": "enterprise"
                    },
                    "createdAt": "2026-06-09T14:02:00.000Z",
                    "updatedAt": "2026-06-09T14:02:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Prospect not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Prospect not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/prospects/suppress": {
      "post": {
        "operationId": "suppressions-suppress",
        "summary": "Suppress prospects by email",
        "description": "Adds emails to your suppression list so those people are never contacted by any campaign. Existing prospects are marked suppressed.\n\nRequired scope: `suppressions:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Suppressions"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 1000,
                    "description": "Emails to suppress (1–1000)."
                  },
                  "reason": {
                    "type": "string",
                    "description": "Optional reason stored with each entry."
                  }
                },
                "required": [
                  "emails"
                ]
              },
              "example": {
                "emails": [
                  "jane@acme.com",
                  "optout@example.com"
                ],
                "reason": "manual opt-out"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "suppressedCount": 2,
                    "alreadySuppressedCount": 0,
                    "notFoundCount": 0,
                    "totalProcessed": 2
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/suppressions": {
      "get": {
        "operationId": "suppressions-list",
        "summary": "List suppression entries",
        "description": "Returns suppressed emails and domains (the blocklist) with cursor pagination.\n\nRequired scope: `suppressions:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "Suppressions"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Filter by entry type.",
            "schema": {
              "type": "string",
              "enum": [
                "email",
                "domain"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "sup_1a2b3c",
                      "type": "email",
                      "value": "optout@example.com",
                      "source": "api",
                      "reason": "manual opt-out",
                      "createdAt": "2026-06-10T12:00:00.000Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/campaigns": {
      "get": {
        "operationId": "campaigns-list",
        "summary": "List campaigns",
        "description": "Returns campaigns with summary stats (sent/opened/replied/...). Cursor paginated.\n\nRequired scope: `campaigns:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filter by status.",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "scheduled",
                "running",
                "paused",
                "completed",
                "error"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                      "name": "Q3 Outbound — Founders",
                      "status": "draft",
                      "channel": "email",
                      "description": null,
                      "timezone": "UTC",
                      "dailySendLimit": 50,
                      "sendingWindowStart": null,
                      "sendingWindowEnd": null,
                      "scheduleDays": null,
                      "stopOnReply": true,
                      "stopOnBounce": true,
                      "stopOnUnsubscribe": true,
                      "trackOpens": true,
                      "trackClicks": true,
                      "totalProspects": 0,
                      "sent": 0,
                      "opened": 0,
                      "clicked": 0,
                      "replied": 0,
                      "bounced": 0,
                      "unsubscribed": 0,
                      "startDate": null,
                      "endDate": null,
                      "createdAt": "2026-06-10T12:00:00.000Z",
                      "updatedAt": "2026-06-10T12:00:00.000Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "campaigns-create",
        "summary": "Create a campaign",
        "description": "Creates a campaign in draft status with one or more steps, assigned mailboxes, and (optionally) enrolled prospects. Start it later with the start endpoint.\n\nRequired scope: `campaigns:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Campaign name."
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Optional description."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "linkedin",
                      "multichannel"
                    ],
                    "default": "email",
                    "description": "Campaign channel."
                  },
                  "linkedinAccountId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "LinkedIn account id (for linkedin/multichannel)."
                  },
                  "timezone": {
                    "type": "string",
                    "maxLength": 100,
                    "default": "UTC",
                    "description": "IANA timezone for the sending schedule."
                  },
                  "dailySendLimit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000,
                    "default": 50,
                    "description": "Daily send cap for the campaign."
                  },
                  "sendingWindowStart": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23,
                    "description": "Start hour (0–23) of the daily sending window."
                  },
                  "sendingWindowEnd": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23,
                    "description": "End hour (0–23) of the daily sending window."
                  },
                  "scheduleDays": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Days of week to send (0=Sun … 6=Sat)."
                  },
                  "stopOnReply": {
                    "type": "boolean",
                    "default": true,
                    "description": "Stop a prospect's sequence when they reply."
                  },
                  "stopOnBounce": {
                    "type": "boolean",
                    "default": true,
                    "description": "Stop on bounce."
                  },
                  "stopOnUnsubscribe": {
                    "type": "boolean",
                    "default": true,
                    "description": "Stop on unsubscribe."
                  },
                  "trackOpens": {
                    "type": "boolean",
                    "default": true,
                    "description": "Track opens."
                  },
                  "trackClicks": {
                    "type": "boolean",
                    "default": true,
                    "description": "Track clicks."
                  },
                  "startDate": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Optional scheduled start."
                  },
                  "endDate": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Optional end date."
                  },
                  "steps": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "description": "Ordered steps. Each: { stepIndex, type (email|linkedin|condition), subject, bodyHtml, bodyText, delayDays, delayHours, isActive, … }."
                  },
                  "mailboxIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 100,
                    "description": "Mailbox ids that send this campaign."
                  },
                  "prospectIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 10000,
                    "description": "Prospect ids to enroll on creation."
                  }
                },
                "required": [
                  "name",
                  "steps",
                  "mailboxIds"
                ]
              },
              "example": {
                "name": "Q3 Outbound — Founders",
                "channel": "email",
                "dailySendLimit": 50,
                "mailboxIds": [
                  "5bd50e20-6b75-4429-9a5a-4a09b46e945a"
                ],
                "steps": [
                  {
                    "stepIndex": 0,
                    "type": "email",
                    "subject": "Quick question, {{firstName}}",
                    "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                    "delayDays": 0
                  },
                  {
                    "stepIndex": 1,
                    "type": "email",
                    "subject": "Re: Quick question",
                    "bodyHtml": "<p>Following up ...</p>",
                    "delayDays": 3,
                    "sendAsReply": true
                  }
                ],
                "prospectIds": [
                  "f3c4a2d1-9b7e-4c2a-8f10-2b6d5e8a1c44"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                    "name": "Q3 Outbound — Founders",
                    "status": "draft",
                    "channel": "email",
                    "description": null,
                    "timezone": "UTC",
                    "dailySendLimit": 50,
                    "sendingWindowStart": null,
                    "sendingWindowEnd": null,
                    "scheduleDays": null,
                    "stopOnReply": true,
                    "stopOnBounce": true,
                    "stopOnUnsubscribe": true,
                    "trackOpens": true,
                    "trackClicks": true,
                    "totalProspects": 0,
                    "sent": 0,
                    "opened": 0,
                    "clicked": 0,
                    "replied": 0,
                    "bounced": 0,
                    "unsubscribed": 0,
                    "startDate": null,
                    "endDate": null,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:00:00.000Z",
                    "steps": [
                      {
                        "id": "s1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                        "stepIndex": 0,
                        "type": "email",
                        "name": "Intro",
                        "subject": "Quick question, {{firstName}}",
                        "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                        "bodyText": "Hi {{firstName}}, ...",
                        "delayDays": 0,
                        "delayHours": null,
                        "isActive": true,
                        "sendAsReply": null,
                        "sentCount": 0,
                        "openCount": 0,
                        "clickCount": 0,
                        "replyCount": 0,
                        "bounceCount": 0,
                        "linkedinActionType": null,
                        "linkedinMessageTemplate": null,
                        "linkedinInviteNote": null,
                        "linkedinSubject": null,
                        "linkedinMaxWaitDays": null,
                        "linkedinEngagementConfig": null,
                        "linkedinInmailConfig": null
                      }
                    ]
                  },
                  "meta": {
                    "prospects_enrolled": 1,
                    "prospects_suppressed": 0,
                    "mailboxes_assigned": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body / step validation failed.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body / step validation failed."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`subscription_blocked` — Your plan doesn't allow this action.; `insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "subscription_blocked",
                    "message": "Your plan doesn't allow this action."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}": {
      "get": {
        "operationId": "campaigns-get",
        "summary": "Get a campaign (with steps)",
        "description": "Returns a single campaign including its ordered steps array.\n\nRequired scope: `campaigns:read`.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                    "name": "Q3 Outbound — Founders",
                    "status": "draft",
                    "channel": "email",
                    "description": null,
                    "timezone": "UTC",
                    "dailySendLimit": 50,
                    "sendingWindowStart": null,
                    "sendingWindowEnd": null,
                    "scheduleDays": null,
                    "stopOnReply": true,
                    "stopOnBounce": true,
                    "stopOnUnsubscribe": true,
                    "trackOpens": true,
                    "trackClicks": true,
                    "totalProspects": 0,
                    "sent": 0,
                    "opened": 0,
                    "clicked": 0,
                    "replied": 0,
                    "bounced": 0,
                    "unsubscribed": 0,
                    "startDate": null,
                    "endDate": null,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:00:00.000Z",
                    "steps": [
                      {
                        "id": "s1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                        "stepIndex": 0,
                        "type": "email",
                        "name": "Intro",
                        "subject": "Quick question, {{firstName}}",
                        "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                        "bodyText": "Hi {{firstName}}, ...",
                        "delayDays": 0,
                        "delayHours": null,
                        "isActive": true,
                        "sendAsReply": null,
                        "sentCount": 0,
                        "openCount": 0,
                        "clickCount": 0,
                        "replyCount": 0,
                        "bounceCount": 0,
                        "linkedinActionType": null,
                        "linkedinMessageTemplate": null,
                        "linkedinInviteNote": null,
                        "linkedinSubject": null,
                        "linkedinMaxWaitDays": null,
                        "linkedinEngagementConfig": null,
                        "linkedinInmailConfig": null
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "campaigns-update",
        "summary": "Update a campaign",
        "description": "Updates campaign settings. Only allowed while the campaign is in draft or paused status.\n\nRequired scope: `campaigns:write`.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "description": "Campaign name."
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000,
                    "description": "Description."
                  },
                  "dailySendLimit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 10000,
                    "description": "Daily send cap."
                  },
                  "sendingWindowStart": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23,
                    "description": "Window start hour."
                  },
                  "sendingWindowEnd": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 23,
                    "description": "Window end hour."
                  },
                  "scheduleDays": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Days of week (0–6)."
                  },
                  "stopOnReply": {
                    "type": "boolean",
                    "description": "Stop on reply."
                  },
                  "stopOnBounce": {
                    "type": "boolean",
                    "description": "Stop on bounce."
                  },
                  "stopOnUnsubscribe": {
                    "type": "boolean",
                    "description": "Stop on unsubscribe."
                  },
                  "trackOpens": {
                    "type": "boolean",
                    "description": "Track opens."
                  },
                  "trackClicks": {
                    "type": "boolean",
                    "description": "Track clicks."
                  },
                  "startDate": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "Scheduled start, or null."
                  },
                  "endDate": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "End date, or null."
                  }
                }
              },
              "example": {
                "dailySendLimit": 80,
                "scheduleDays": [
                  1,
                  2,
                  3,
                  4,
                  5
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                    "name": "Q3 Outbound — Founders",
                    "status": "draft",
                    "channel": "email",
                    "description": null,
                    "timezone": "UTC",
                    "dailySendLimit": 80,
                    "sendingWindowStart": null,
                    "sendingWindowEnd": null,
                    "scheduleDays": [
                      1,
                      2,
                      3,
                      4,
                      5
                    ],
                    "stopOnReply": true,
                    "stopOnBounce": true,
                    "stopOnUnsubscribe": true,
                    "trackOpens": true,
                    "trackClicks": true,
                    "totalProspects": 0,
                    "sent": 0,
                    "opened": 0,
                    "clicked": 0,
                    "replied": 0,
                    "bounced": 0,
                    "unsubscribed": 0,
                    "startDate": null,
                    "endDate": null,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:00:00.000Z",
                    "steps": [
                      {
                        "id": "s1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                        "stepIndex": 0,
                        "type": "email",
                        "name": "Intro",
                        "subject": "Quick question, {{firstName}}",
                        "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                        "bodyText": "Hi {{firstName}}, ...",
                        "delayDays": 0,
                        "delayHours": null,
                        "isActive": true,
                        "sendAsReply": null,
                        "sentCount": 0,
                        "openCount": 0,
                        "clickCount": 0,
                        "replyCount": 0,
                        "bounceCount": 0,
                        "linkedinActionType": null,
                        "linkedinMessageTemplate": null,
                        "linkedinInviteNote": null,
                        "linkedinSubject": null,
                        "linkedinMaxWaitDays": null,
                        "linkedinEngagementConfig": null,
                        "linkedinInmailConfig": null
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_status` — Campaign isn't in draft/paused status.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "invalid_status",
                    "message": "Campaign isn't in draft/paused status."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/start": {
      "post": {
        "operationId": "campaigns-start",
        "summary": "Start a campaign",
        "description": "Moves a draft/paused campaign into running. No request body.\n\nRequired scope: `campaigns:write`.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                    "name": "Q3 Outbound — Founders",
                    "status": "running",
                    "channel": "email",
                    "description": null,
                    "timezone": "UTC",
                    "dailySendLimit": 50,
                    "sendingWindowStart": null,
                    "sendingWindowEnd": null,
                    "scheduleDays": null,
                    "stopOnReply": true,
                    "stopOnBounce": true,
                    "stopOnUnsubscribe": true,
                    "trackOpens": true,
                    "trackClicks": true,
                    "totalProspects": 0,
                    "sent": 0,
                    "opened": 0,
                    "clicked": 0,
                    "replied": 0,
                    "bounced": 0,
                    "unsubscribed": 0,
                    "startDate": null,
                    "endDate": null,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:00:00.000Z",
                    "steps": [
                      {
                        "id": "s1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                        "stepIndex": 0,
                        "type": "email",
                        "name": "Intro",
                        "subject": "Quick question, {{firstName}}",
                        "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                        "bodyText": "Hi {{firstName}}, ...",
                        "delayDays": 0,
                        "delayHours": null,
                        "isActive": true,
                        "sendAsReply": null,
                        "sentCount": 0,
                        "openCount": 0,
                        "clickCount": 0,
                        "replyCount": 0,
                        "bounceCount": 0,
                        "linkedinActionType": null,
                        "linkedinMessageTemplate": null,
                        "linkedinInviteNote": null,
                        "linkedinSubject": null,
                        "linkedinMaxWaitDays": null,
                        "linkedinEngagementConfig": null,
                        "linkedinInmailConfig": null
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_status` — Campaign can't be started from its current status.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "invalid_status",
                    "message": "Campaign can't be started from its current status."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`subscription_blocked` — Your plan doesn't allow this action.; `insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "subscription_blocked",
                    "message": "Your plan doesn't allow this action."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/pause": {
      "post": {
        "operationId": "campaigns-pause",
        "summary": "Pause a campaign",
        "description": "Pauses a running campaign. No request body.\n\nRequired scope: `campaigns:write`.",
        "tags": [
          "Campaigns"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "c1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                    "name": "Q3 Outbound — Founders",
                    "status": "paused",
                    "channel": "email",
                    "description": null,
                    "timezone": "UTC",
                    "dailySendLimit": 50,
                    "sendingWindowStart": null,
                    "sendingWindowEnd": null,
                    "scheduleDays": null,
                    "stopOnReply": true,
                    "stopOnBounce": true,
                    "stopOnUnsubscribe": true,
                    "trackOpens": true,
                    "trackClicks": true,
                    "totalProspects": 0,
                    "sent": 0,
                    "opened": 0,
                    "clicked": 0,
                    "replied": 0,
                    "bounced": 0,
                    "unsubscribed": 0,
                    "startDate": null,
                    "endDate": null,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:00:00.000Z",
                    "steps": [
                      {
                        "id": "s1a2b3c4-d5e6-47f8-9a0b-1c2d3e4f5a6b",
                        "stepIndex": 0,
                        "type": "email",
                        "name": "Intro",
                        "subject": "Quick question, {{firstName}}",
                        "bodyHtml": "<p>Hi {{firstName}}, ...</p>",
                        "bodyText": "Hi {{firstName}}, ...",
                        "delayDays": 0,
                        "delayHours": null,
                        "isActive": true,
                        "sendAsReply": null,
                        "sentCount": 0,
                        "openCount": 0,
                        "clickCount": 0,
                        "replyCount": 0,
                        "bounceCount": 0,
                        "linkedinActionType": null,
                        "linkedinMessageTemplate": null,
                        "linkedinInviteNote": null,
                        "linkedinSubject": null,
                        "linkedinMaxWaitDays": null,
                        "linkedinEngagementConfig": null,
                        "linkedinInmailConfig": null
                      }
                    ]
                  },
                  "meta": {
                    "request_id": "req_mq28denhy91fh6"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_status` — Campaign isn't running.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "invalid_status",
                    "message": "Campaign isn't running."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/campaigns/{id}/enrollments": {
      "post": {
        "operationId": "enrollments-create",
        "summary": "Enroll prospects",
        "description": "Adds prospects to a campaign by prospect id, audience list id, and/or email. Suppressed prospects are skipped and counted separately. Provide at least one of prospectIds, listIds, emails.\n\nRequired scope: `enrollments:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Enrollments"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prospectIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Prospect ids to enroll."
                  },
                  "listIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Audience list ids — every prospect on each list is enrolled."
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Prospect emails to enroll."
                  }
                }
              },
              "example": {
                "emails": [
                  "jane@acme.com"
                ],
                "listIds": [
                  "list_9f3a2b"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "enrolledCount": 12,
                    "suppressedCount": 1,
                    "invalidCount": 0,
                    "alreadyEnrolledCount": 2,
                    "totalProcessed": 15
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — No targets given or body invalid.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "No targets given or body invalid."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "enrollments-delete",
        "summary": "Unenroll prospects",
        "description": "Removes prospects from a campaign (soft-stop — their audit history is preserved and any pending sends are cancelled). Provide at least one of prospectIds, emails.\n\nRequired scope: `enrollments:write`.",
        "tags": [
          "Enrollments"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Campaign id (UUID).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "prospectIds": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Prospect ids to unenroll."
                  },
                  "emails": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Prospect emails to unenroll."
                  }
                }
              },
              "example": {
                "emails": [
                  "jane@acme.com"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "unenrolledCount": 1,
                    "totalProcessed": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — No targets given or body invalid.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "No targets given or body invalid."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Campaign not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Campaign not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "webhooks-list",
        "summary": "List webhooks",
        "description": "Returns your configured webhook endpoints (without secrets).\n\nRequired scope: `webhooks:read`.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "wh_2c1a9f",
                      "url": "https://example.com/hooks/warmysender",
                      "events": [
                        "reply.received",
                        "email.bounced"
                      ],
                      "isActive": true,
                      "lastTriggeredAt": null,
                      "failureCount": 0,
                      "createdAt": "2026-06-10T12:00:00.000Z",
                      "updatedAt": "2026-06-10T12:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "webhooks-create",
        "summary": "Create a webhook",
        "description": "Registers a webhook endpoint for one or more event types. The signing secret (whsec_…) is returned ONCE in this response — store it; you'll use it to verify payload signatures.\n\nRequired scope: `webhooks:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 500,
                    "format": "uri",
                    "description": "HTTPS URL that receives POST deliveries."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Event types to subscribe to (see Webhook Events)."
                  }
                },
                "required": [
                  "url",
                  "events"
                ]
              },
              "example": {
                "url": "https://example.com/hooks/warmysender",
                "events": [
                  "reply.received",
                  "email.bounced",
                  "linkedin.reply_received"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "wh_2c1a9f",
                    "url": "https://example.com/hooks/warmysender",
                    "events": [
                      "reply.received",
                      "email.bounced",
                      "linkedin.reply_received"
                    ],
                    "isActive": true,
                    "secret": "whsec_3f9a...redacted",
                    "createdAt": "2026-06-10T12:00:00.000Z"
                  },
                  "message": "Webhook created. Save the secret - it will not be shown again."
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Invalid URL or unknown event type.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Invalid URL or unknown event type."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "patch": {
        "operationId": "webhooks-update",
        "summary": "Update a webhook",
        "description": "Change a webhook's URL, subscribed events, or active flag.\n\nRequired scope: `webhooks:write`.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 500,
                    "format": "uri",
                    "description": "New delivery URL."
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "description": "Replacement list of event types."
                  },
                  "isActive": {
                    "type": "boolean",
                    "description": "Enable or disable deliveries."
                  }
                }
              },
              "example": {
                "isActive": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": "wh_2c1a9f",
                    "url": "https://example.com/hooks/warmysender",
                    "events": [
                      "reply.received"
                    ],
                    "isActive": false,
                    "lastTriggeredAt": null,
                    "failureCount": 0,
                    "createdAt": "2026-06-10T12:00:00.000Z",
                    "updatedAt": "2026-06-10T12:05:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`validation_error` — Body failed validation.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "validation_error",
                    "message": "Body failed validation."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Webhook not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Webhook not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "webhooks-delete",
        "summary": "Delete a webhook",
        "description": "Permanently removes a webhook endpoint. Returns 204 with no body.\n\nRequired scope: `webhooks:write`.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Success — no response body."
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Webhook not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Webhook not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "operationId": "webhooks-test",
        "summary": "Send a test event",
        "description": "Queues a webhook.test delivery to the endpoint so you can verify signature handling end-to-end. No request body.\n\nRequired scope: `webhooks:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Webhook id.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "eventId": "evt_a1b2c3",
                    "status": "queued",
                    "message": "Test webhook event has been queued for delivery"
                  }
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — Webhook not found.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "not_found",
                    "message": "Webhook not found."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/linkedin/accounts": {
      "get": {
        "operationId": "linkedin-accounts-list",
        "summary": "List LinkedIn accounts",
        "description": "Returns connected LinkedIn accounts with their daily engagement limits and how many actions remain today.\n\nRequired scope: `linkedin:read`.",
        "tags": [
          "LinkedIn"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results to return (1–100).",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "li_5a2b1c",
                      "name": "Jordan Lee",
                      "linkedin_url": "https://www.linkedin.com/in/jordanlee",
                      "status": "connected",
                      "linkedin_account_type": "classic",
                      "strategy": "steady",
                      "ramp_week": 3,
                      "engagements_today": 4,
                      "engagements_day": "2026-06-10",
                      "created_at": "2026-05-20T10:00:00.000Z",
                      "daily_limits": {
                        "engagements_per_day": 30,
                        "engagements_remaining": 26
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "unauthorized",
                    "message": "Missing or invalid API key."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/linkedin/posts/{postId}/reactions": {
      "post": {
        "operationId": "linkedin-reactions-add",
        "summary": "React to a post",
        "description": "Adds a reaction (like, celebrate, etc.) to a LinkedIn post from one of your connected accounts. Subject to per-account daily engagement limits — account safety always wins.\n\nRequired scope: `linkedin:write`.\n\nRequires a unique `Idempotency-Key` request header so retries never duplicate.",
        "tags": [
          "LinkedIn"
        ],
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "LinkedIn post id (URN).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "linkedin_account_id": {
                    "type": "string",
                    "description": "Which connected LinkedIn account reacts."
                  },
                  "reaction_type": {
                    "type": "string",
                    "enum": [
                      "LIKE",
                      "CELEBRATE",
                      "SUPPORT",
                      "LOVE",
                      "INSIGHTFUL",
                      "FUNNY"
                    ],
                    "default": "LIKE",
                    "description": "Reaction (case-insensitive; defaults to LIKE)."
                  }
                },
                "required": [
                  "linkedin_account_id"
                ]
              },
              "example": {
                "linkedin_account_id": "li_5a2b1c",
                "reaction_type": "LIKE"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "post_id": "urn:li:activity:7300000000000000000",
                    "reaction_type": "LIKE",
                    "linkedin_account_id": "li_5a2b1c"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`account_not_connected` — The LinkedIn account isn't connected.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "account_not_connected",
                    "message": "The LinkedIn account isn't connected."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`account_unauthorized` — The LinkedIn session needs re-authentication.; `unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "account_unauthorized",
                    "message": "The LinkedIn session needs re-authentication."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`daily_limit_reached` — The account hit its daily engagement limit.; `rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "daily_limit_reached",
                    "message": "The account hit its daily engagement limit."
                  }
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "linkedin-reactions-list",
        "summary": "List reactions on a post",
        "description": "Lists who reacted to a post, as seen by one of your connected accounts. Cursor paginated.\n\nRequired scope: `linkedin:read`.\n\nReturns a cursor-paginated list — pass `cursor` from the previous page to continue.",
        "tags": [
          "LinkedIn"
        ],
        "parameters": [
          {
            "name": "postId",
            "in": "path",
            "required": true,
            "description": "LinkedIn post id (URN).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "linkedin_account_id",
            "in": "query",
            "required": true,
            "description": "Which connected account performs the read.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Results per page (1–100).",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor from the previous page.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "user_id": "urn:li:person:abc",
                      "name": "Sam Rivera",
                      "reaction_type": "LIKE",
                      "timestamp": "2026-06-10T11:00:00.000Z"
                    }
                  ],
                  "pagination": {
                    "has_more": false,
                    "next_cursor": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "`account_not_connected` — The LinkedIn account isn't connected.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "account_not_connected",
                    "message": "The LinkedIn account isn't connected."
                  }
                }
              }
            }
          },
          "401": {
            "description": "`account_unauthorized` — The LinkedIn session needs re-authentication.; `unauthorized` — Missing or invalid API key.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "account_unauthorized",
                    "message": "The LinkedIn session needs re-authentication."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` — The API key lacks the scope this endpoint requires.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "insufficient_scope",
                    "message": "The API key lacks the scope this endpoint requires."
                  }
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — Too many requests — slow down and retry after the Retry-After delay.",
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "code": "rate_limited",
                    "message": "Too many requests — slow down and retry after the Retry-After delay."
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "x-webhook-events": [
    {
      "type": "reply.received",
      "description": "A prospect replied (email or LinkedIn).",
      "payloadExample": {
        "prospectId": "f3c4a2d1-...",
        "prospectEmail": "jane@acme.com",
        "campaignId": "c1a2b3c4-...",
        "mailboxId": "5bd50e20-...",
        "subject": "Re: Quick question",
        "messageId": "<...>",
        "receivedAt": "2026-06-10T11:00:00.000Z",
        "channel": "email"
      }
    },
    {
      "type": "email.bounced",
      "description": "An outbound email bounced (hard or soft).",
      "payloadExample": {
        "prospectEmail": "jane@acme.com",
        "campaignId": "c1a2b3c4-...",
        "mailboxId": "5bd50e20-...",
        "bounceType": "hard",
        "bounceReason": "550 user unknown",
        "bouncedAt": "2026-06-10T11:01:00.000Z"
      }
    },
    {
      "type": "email.unsubscribed",
      "description": "A prospect unsubscribed.",
      "payloadExample": {
        "prospectId": "f3c4a2d1-...",
        "prospectEmail": "jane@acme.com",
        "campaignId": "c1a2b3c4-...",
        "unsubscribedAt": "2026-06-10T11:02:00.000Z"
      }
    },
    {
      "type": "email.opened",
      "description": "A tracked email was opened.",
      "payloadExample": {
        "prospectId": "f3c4a2d1-...",
        "prospectEmail": "jane@acme.com",
        "campaignId": "c1a2b3c4-...",
        "stepIndex": 0,
        "openedAt": "2026-06-10T11:03:00.000Z"
      }
    },
    {
      "type": "email.clicked",
      "description": "A tracked link was clicked.",
      "payloadExample": {
        "prospectId": "f3c4a2d1-...",
        "prospectEmail": "jane@acme.com",
        "campaignId": "c1a2b3c4-...",
        "url": "https://yourdomain.com/demo",
        "clickedAt": "2026-06-10T11:04:00.000Z"
      }
    },
    {
      "type": "prospect.suppressed",
      "description": "A prospect was added to the suppression list.",
      "payloadExample": {
        "prospectId": "f3c4a2d1-...",
        "email": "jane@acme.com",
        "reason": "manual opt-out",
        "suppressedAt": "2026-06-10T11:05:00.000Z"
      }
    },
    {
      "type": "limit.hit",
      "description": "A sending limit (mailbox/domain/prospect/cooldown) was reached.",
      "payloadExample": {
        "limitType": "daily_mailbox",
        "mailboxId": "5bd50e20-...",
        "currentValue": 50,
        "limitValue": 50,
        "hitAt": "2026-06-10T11:06:00.000Z"
      }
    },
    {
      "type": "linkedin.invite_accepted",
      "description": "A LinkedIn connection invite was accepted.",
      "payloadExample": {
        "prospectName": "Sam Rivera",
        "prospectLinkedinUrl": "https://www.linkedin.com/in/samrivera",
        "campaignId": "c1a2b3c4-...",
        "enrollmentId": "enr_...",
        "linkedinAccountId": "li_5a2b1c",
        "acceptedAt": "2026-06-10T11:07:00.000Z"
      }
    },
    {
      "type": "linkedin.reply_received",
      "description": "A LinkedIn message reply was received.",
      "payloadExample": {
        "prospectName": "Sam Rivera",
        "prospectLinkedinUrl": "https://www.linkedin.com/in/samrivera",
        "campaignId": "c1a2b3c4-...",
        "enrollmentId": "enr_...",
        "linkedinAccountId": "li_5a2b1c",
        "messageText": "Sure, let's talk",
        "threadId": "th_...",
        "receivedAt": "2026-06-10T11:08:00.000Z"
      }
    },
    {
      "type": "webhook.test",
      "description": "A manual test event sent from the test endpoint.",
      "payloadExample": {
        "webhookId": "wh_2c1a9f",
        "timestamp": "2026-06-10T11:09:00.000Z",
        "message": "This is a test event from WarmySender"
      }
    }
  ]
}