{
  "openapi": "3.1.0",
  "info": {
    "title": "Furnace Client API",
    "version": "1.15.0",
    "description": "Account-scoped REST API for campaigns, leads, people, saved lists, inbox, mailboxes, mailbox tags, stats, and block list.\n\nHuman-readable guides and API reference: **https://api.getfurnace.io/docs**"
  },
  "servers": [
    {
      "url": "https://api.getfurnace.io"
    }
  ],
  "tags": [
    {
      "name": "Campaigns",
      "description": "Read and mutate campaigns that belong to the authenticated account."
    },
    {
      "name": "Flow",
      "description": "Read, validate, and update campaign flow graphs."
    },
    {
      "name": "Leads",
      "description": "Manage campaign leads, including single-row upserts and bulk imports."
    },
    {
      "name": "Lead fields",
      "description": "Inspect and extend required lead-field mappings derived from the campaign flow."
    },
    {
      "name": "Jobs",
      "description": "Create and poll asynchronous bulk jobs (import, add/remove, pause/resume)."
    },
    {
      "name": "People",
      "description": "Account-scoped people explorer and profile updates."
    },
    {
      "name": "Lead lists",
      "description": "Saved lead lists and list membership."
    },
    {
      "name": "Mailboxes",
      "description": "Read account mailboxes, manage mailbox tags, and keep secret password fields out of responses."
    },
    {
      "name": "Inbox",
      "description": "List and triage inbox threads, read messages, send replies and forwards, manage message jobs, out-of-office state, lead replacement, and thread tags."
    },
    {
      "name": "Block list",
      "description": "List, add, and remove blocked email addresses or domain hosts. A domain entry matches the exact host only (`example.com` → `*@example.com`, not subdomains)."
    },
    {
      "name": "Stats",
      "description": "Read daily and aggregate campaign performance statistics."
    },
    {
      "name": "Webhooks",
      "description": "Read and update account webhook URL, signing secret, and enabled events."
    },
    {
      "name": "API keys",
      "description": "List, create, and revoke account API keys. Create returns the secret once."
    },
    {
      "name": "Meta",
      "description": "Service metadata endpoints."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "Use an account API key in the Authorization header: `Authorization: Bearer f_...`."
      }
    },
    "headers": {
      "XRateLimitLimit": {
        "description": "Maximum requests allowed in the current minute window. Furnace currently allows 200 requests per account per minute.",
        "schema": {
          "type": "string",
          "example": "200"
        }
      },
      "XRateLimitRemaining": {
        "description": "Remaining requests in the current minute window.",
        "schema": {
          "type": "string",
          "example": "199"
        }
      },
      "XRateLimitReset": {
        "description": "Unix epoch seconds when the current rate-limit window resets.",
        "schema": {
          "type": "string",
          "example": "1716316860"
        }
      }
    },
    "parameters": {
      "CampaignId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Campaign id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "LeadId": {
        "name": "leadId",
        "in": "path",
        "required": true,
        "description": "Lead id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "FlowNodeId": {
        "name": "nodeId",
        "in": "path",
        "required": true,
        "description": "Flow node id.",
        "schema": {
          "type": "string"
        }
      },
      "JobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Async import job id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MailboxId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Mailbox id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ApiKeyId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "API key id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MailboxConnectSessionId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Mailbox connect session id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ThreadId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Inbox thread id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "BlockListId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Block-list entry id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Number of rows to return. Defaults to 20; maximum 100.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 20,
          "maximum": 100
        }
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "description": "Zero-based offset for pagination.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "Search": {
        "name": "q",
        "in": "query",
        "description": "Case-insensitive prefix search across thread subject, participants, lead name/email/company, campaign name, thread tags, and message bodies (min 2 characters).",
        "schema": {
          "type": "string"
        }
      },
      "CampaignStatus": {
        "name": "status",
        "in": "query",
        "description": "Campaign status filter.",
        "schema": {
          "type": "string",
          "enum": [
            "draft",
            "scheduled",
            "running",
            "paused",
            "stopped"
          ]
        }
      },
      "CampaignTagIds": {
        "name": "tag_ids",
        "in": "query",
        "description": "Comma-separated campaign tag ids. Returns campaigns that have any of the listed tags.",
        "schema": {
          "type": "string",
          "example": "uuid-1,uuid-2"
        }
      },
      "CampaignTagId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Campaign tag id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MailboxTagIds": {
        "name": "tag_ids",
        "in": "query",
        "description": "Comma-separated mailbox tag ids. Returns mailboxes that have any of the listed tags.",
        "schema": {
          "type": "string",
          "example": "uuid-1,uuid-2"
        }
      },
      "MailboxTagId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Mailbox tag id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "GlobalLeadId": {
        "name": "globalLeadId",
        "in": "path",
        "required": true,
        "description": "Stable account-scoped person id (SHA-256 of normalized email).",
        "schema": {
          "type": "string"
        }
      },
      "LeadListId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Saved lead list id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "PeopleSearch": {
        "name": "q",
        "in": "query",
        "description": "Search people by email or name.",
        "schema": {
          "type": "string"
        }
      },
      "PeopleSort": {
        "name": "sort",
        "in": "query",
        "description": "Sort column for the people explorer.",
        "schema": {
          "type": "string",
          "default": "latest_activity"
        }
      },
      "PeopleSortDirection": {
        "name": "sort_dir",
        "in": "query",
        "description": "Sort direction.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "default": "desc"
        }
      },
      "GlobalLeadIdsQuery": {
        "name": "global_lead_ids",
        "in": "query",
        "description": "Comma-separated global lead ids filter.",
        "schema": {
          "type": "string"
        }
      },
      "CampaignIdsQuery": {
        "name": "campaign_ids",
        "in": "query",
        "description": "Comma-separated campaign ids filter.",
        "schema": {
          "type": "string"
        }
      },
      "IncludeDeletedCampaigns": {
        "name": "include_deleted",
        "in": "query",
        "description": "When true, includes campaigns with `deleted_at` set.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "CampaignFilter": {
        "name": "campaign_id",
        "in": "query",
        "description": "Filter inbox threads to a single campaign.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MailboxFilter": {
        "name": "mailbox_id",
        "in": "query",
        "description": "Filter inbox threads to a single mailbox.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "MessageJobId": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Outbound inbox message job id returned by reply or forward endpoints.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "UnreadOnly": {
        "name": "unread_only",
        "in": "query",
        "description": "When true, returns only threads with unread received messages.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      },
      "ConversationStatusFilter": {
        "name": "conversation_status",
        "in": "query",
        "description": "Filter threads by conversation status.",
        "schema": {
          "type": "string",
          "enum": [
            "open",
            "closed"
          ]
        }
      },
      "ThreadCategoryFilter": {
        "name": "category",
        "in": "query",
        "description": "Filter threads by category. Use `no_category` for uncategorized threads.",
        "schema": {
          "type": "string",
          "enum": [
            "Interested",
            "Neutral",
            "Not Interested",
            "Auto Reply",
            "no_category"
          ]
        }
      },
      "ThreadTagIdsFilter": {
        "name": "tag_ids",
        "in": "query",
        "description": "Comma-separated thread tag ids. Returns threads tagged with any listed tag.",
        "schema": {
          "type": "string",
          "example": "uuid-1,uuid-2"
        }
      },
      "DateFrom": {
        "name": "date_from",
        "in": "query",
        "description": "Inclusive ISO-8601 timestamp filter on `last_inbound_at` (latest lead reply).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "DateTo": {
        "name": "date_to",
        "in": "query",
        "description": "Inclusive ISO-8601 timestamp filter on `last_inbound_at` (latest lead reply).",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "HasReplyOnly": {
        "name": "has_reply_only",
        "in": "query",
        "description": "When true (default), returns only threads with at least one inbound reply.",
        "schema": {
          "type": "boolean",
          "default": true
        }
      },
      "StartDate": {
        "name": "start_date",
        "in": "query",
        "description": "Inclusive start date in `YYYY-MM-DD` format.",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "EndDate": {
        "name": "end_date",
        "in": "query",
        "description": "Inclusive end date in `YYYY-MM-DD` format.",
        "schema": {
          "type": "string",
          "format": "date"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "description": "Optional idempotency key for campaign create, lead create, and bulk lead imports. Retries with the same key and body return the cached response.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "UnauthorizedError": {
        "description": "Missing, invalid, revoked, or expired API key.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "invalid_api_key",
                "message": "A valid Furnace API key is required"
              }
            }
          }
        }
      },
      "ForbiddenError": {
        "description": "The authenticated account may read the resource but cannot perform this action.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "permission_error",
                "code": "smartlead_read_only",
                "message": "Smartlead campaigns are read-only via the API"
              }
            }
          }
        }
      },
      "NotFoundError": {
        "description": "The requested resource does not exist in the API key account scope.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "campaign_not_found",
                "message": "Campaign not found"
              }
            }
          }
        }
      },
      "ConflictError": {
        "description": "The request conflicts with the current resource state.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "target_missing_enrollment",
                "message": "The existing contact for this address has no active enrollment in this campaign; launch the campaign or re-add the contact before replacing. Call GET /v1/threads/{id}/replace-lead/preview to inspect the match first."
              }
            }
          }
        }
      },
      "RateLimitError": {
        "description": "The account exceeded the current rate limit window.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "rate_limit_error",
                "code": "rate_limit_exceeded",
                "message": "Rate limit exceeded for this account"
              }
            }
          }
        }
      },
      "ValidationError": {
        "description": "The request body or parameters failed validation.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "invalid_flow",
                "message": "Flow validation failed"
              },
              "details": [
                {
                  "path": "nodes[1].data.variants[0].id",
                  "code": "invalid_variant_id",
                  "message": "Email variants must have a stable UUID id."
                }
              ]
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server-side error.",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "api_error",
                "code": "internal_error",
                "message": "Internal server error"
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "invalid_request_error",
              "authentication_error",
              "permission_error",
              "rate_limit_error",
              "api_error"
            ]
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "param": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "code",
          "message"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "permission_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "param": {
                "type": "string"
              }
            },
            "required": [
              "type",
              "code",
              "message"
            ]
          },
          "details": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowValidationIssue"
            }
          }
        },
        "required": [
          "error"
        ]
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "error"
            ]
          },
          "db": {
            "type": "string",
            "enum": [
              "ok",
              "error"
            ]
          }
        },
        "required": [
          "status",
          "db"
        ]
      },
      "DeleteResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "deleted": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "deleted"
        ]
      },
      "CampaignTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "created_at"
        ]
      },
      "CampaignTagCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "CampaignTagUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "CampaignTagResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignTag"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignTagListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignTag"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "Campaign": {
        "type": "object",
        "description": "Campaign row as returned by the Furnace backend.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "bucket_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "scheduled",
              "running",
              "paused",
              "stopped"
            ]
          },
          "source": {
            "type": "string",
            "description": "Campaign source. `smartlead` campaigns can be read but not mutated through this API.",
            "examples": [
              "manual"
            ]
          },
          "flow_data": {
            "$ref": "#/components/schemas/CampaignFlow"
          },
          "schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignSchedule"
              }
            ],
            "nullable": true,
            "description": "Send window. `null` means send 24/7."
          },
          "sending_interval_seconds": {
            "type": "number",
            "nullable": true
          },
          "lifecycle_schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignLifecycleSchedule"
              }
            ],
            "nullable": true,
            "description": "Optional calendar start and exclusive pause dates in `time_zone`. Null dates mean launch immediately and never auto-pause. `start_at`/`pause_at` are read-only derived UTC instants."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignTag"
            },
            "description": "Campaign tags assigned to this campaign."
          },
          "mailbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Mailbox ids currently attached to this campaign."
          }
        },
        "required": [
          "id",
          "status",
          "created_at"
        ],
        "additionalProperties": false
      },
      "CampaignFlow": {
        "type": "object",
        "description": "Directed acyclic graph of campaign steps (`nodes` + `edges`). See [Email sequences](/docs/concepts/sequences/) for a plain-language overview, or expand the properties below.",
        "properties": {
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowNode"
            }
          },
          "edges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowEdge"
            }
          }
        },
        "required": [
          "nodes",
          "edges"
        ],
        "additionalProperties": false,
        "example": {
          "nodes": [
            {
              "id": "leadSource-1",
              "type": "leadSource",
              "position": {
                "x": 0,
                "y": 0
              },
              "data": {
                "label": "Lead Bucket",
                "customFieldKeys": [
                  "company"
                ],
                "mappedStandardFieldKeys": [
                  "email",
                  "first_name",
                  "last_name"
                ],
                "isRequired": true
              },
              "deletable": false
            },
            {
              "id": "email-1",
              "type": "email",
              "position": {
                "x": 220,
                "y": 0
              },
              "data": {
                "label": "Intro Email",
                "priority": false,
                "variants": [
                  {
                    "id": "11111111-1111-4111-8111-111111111111",
                    "label": "A",
                    "subject": "Quick question for {{first_name}}",
                    "template": "Hi {{first_name}} - reaching out about {{custom.company}}.",
                    "isActive": true,
                    "order": 0
                  },
                  {
                    "id": "11111111-1111-4111-8111-111111111112",
                    "label": "B",
                    "subject": "Following up for {{first_name}}",
                    "template": "Hi {{first_name}} - wanted to share a quick idea for {{custom.company}}.",
                    "isActive": true,
                    "order": 1
                  }
                ]
              }
            },
            {
              "id": "waitTime-1",
              "type": "waitTime",
              "position": {
                "x": 460,
                "y": 0
              },
              "data": {
                "label": "Wait 1 day",
                "duration": "1",
                "unit": "days",
                "wait_duration_seconds": 86400
              }
            },
            {
              "id": "email-2",
              "type": "email",
              "position": {
                "x": 700,
                "y": 0
              },
              "data": {
                "label": "Follow-up",
                "priority": false,
                "variants": [
                  {
                    "id": "22222222-2222-4222-8222-222222222221",
                    "label": "A",
                    "subject": "Bumping this for {{first_name}}",
                    "template": "Hi {{first_name}} - circling back in case this is relevant for {{custom.company}}.",
                    "isActive": true,
                    "order": 0
                  },
                  {
                    "id": "22222222-2222-4222-8222-222222222222",
                    "label": "B",
                    "subject": "Any thoughts, {{first_name}}?",
                    "template": "Hi {{first_name}} - should I close the loop or send more detail?",
                    "isActive": true,
                    "order": 1
                  }
                ]
              }
            }
          ],
          "edges": [
            {
              "id": "e1",
              "source": "leadSource-1",
              "target": "email-1"
            },
            {
              "id": "e2",
              "source": "email-1",
              "target": "waitTime-1"
            },
            {
              "id": "e3",
              "source": "waitTime-1",
              "target": "email-2"
            }
          ]
        },
        "examples": {
          "linear": {
            "summary": "Email → wait → email",
            "value": {
              "nodes": [
                {
                  "id": "leadSource-1",
                  "type": "leadSource",
                  "position": {
                    "x": 0,
                    "y": 0
                  },
                  "data": {
                    "label": "Lead Bucket",
                    "customFieldKeys": [
                      "company"
                    ],
                    "mappedStandardFieldKeys": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "isRequired": true
                  },
                  "deletable": false
                },
                {
                  "id": "email-1",
                  "type": "email",
                  "position": {
                    "x": 220,
                    "y": 0
                  },
                  "data": {
                    "label": "Intro Email",
                    "priority": false,
                    "variants": [
                      {
                        "id": "11111111-1111-4111-8111-111111111111",
                        "label": "A",
                        "subject": "Quick question for {{first_name}}",
                        "template": "Hi {{first_name}} - reaching out about {{custom.company}}.",
                        "isActive": true,
                        "order": 0
                      },
                      {
                        "id": "11111111-1111-4111-8111-111111111112",
                        "label": "B",
                        "subject": "Following up for {{first_name}}",
                        "template": "Hi {{first_name}} - wanted to share a quick idea for {{custom.company}}.",
                        "isActive": true,
                        "order": 1
                      }
                    ]
                  }
                },
                {
                  "id": "waitTime-1",
                  "type": "waitTime",
                  "position": {
                    "x": 460,
                    "y": 0
                  },
                  "data": {
                    "label": "Wait 1 day",
                    "duration": "1",
                    "unit": "days",
                    "wait_duration_seconds": 86400
                  }
                },
                {
                  "id": "email-2",
                  "type": "email",
                  "position": {
                    "x": 700,
                    "y": 0
                  },
                  "data": {
                    "label": "Follow-up",
                    "priority": false,
                    "variants": [
                      {
                        "id": "22222222-2222-4222-8222-222222222221",
                        "label": "A",
                        "subject": "Bumping this for {{first_name}}",
                        "template": "Hi {{first_name}} - circling back in case this is relevant for {{custom.company}}.",
                        "isActive": true,
                        "order": 0
                      },
                      {
                        "id": "22222222-2222-4222-8222-222222222222",
                        "label": "B",
                        "subject": "Any thoughts, {{first_name}}?",
                        "template": "Hi {{first_name}} - should I close the loop or send more detail?",
                        "isActive": true,
                        "order": 1
                      }
                    ]
                  }
                }
              ],
              "edges": [
                {
                  "id": "e1",
                  "source": "leadSource-1",
                  "target": "email-1"
                },
                {
                  "id": "e2",
                  "source": "email-1",
                  "target": "waitTime-1"
                },
                {
                  "id": "e3",
                  "source": "waitTime-1",
                  "target": "email-2"
                }
              ]
            }
          },
          "categorizer": {
            "summary": "Categorizer branch",
            "value": {
              "nodes": [
                {
                  "id": "leadSource-1",
                  "type": "leadSource",
                  "position": {
                    "x": 0,
                    "y": 0
                  },
                  "data": {
                    "label": "Lead Bucket",
                    "customFieldKeys": [
                      "company"
                    ],
                    "mappedStandardFieldKeys": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "isRequired": true
                  },
                  "deletable": false
                },
                {
                  "id": "email-1",
                  "type": "email",
                  "position": {
                    "x": 220,
                    "y": 0
                  },
                  "data": {
                    "label": "Intro Email",
                    "priority": false,
                    "variants": [
                      {
                        "id": "11111111-1111-4111-8111-111111111111",
                        "label": "A",
                        "subject": "Quick question for {{first_name}}",
                        "template": "Hi {{first_name}} - reaching out about {{custom.company}}.",
                        "isActive": true,
                        "order": 0
                      },
                      {
                        "id": "11111111-1111-4111-8111-111111111112",
                        "label": "B",
                        "subject": "Following up for {{first_name}}",
                        "template": "Hi {{first_name}} - wanted to share a quick idea for {{custom.company}}.",
                        "isActive": true,
                        "order": 1
                      }
                    ]
                  }
                },
                {
                  "id": "waitTime-1",
                  "type": "waitTime",
                  "position": {
                    "x": 460,
                    "y": 0
                  },
                  "data": {
                    "label": "Wait 1 day",
                    "duration": "1",
                    "unit": "days",
                    "wait_duration_seconds": 86400
                  }
                },
                {
                  "id": "email-2",
                  "type": "email",
                  "position": {
                    "x": 700,
                    "y": 0
                  },
                  "data": {
                    "label": "Reply Trigger",
                    "priority": false,
                    "variants": [
                      {
                        "id": "22222222-2222-4222-8222-222222222221",
                        "label": "A",
                        "subject": "Checking back in, {{first_name}}",
                        "template": "Hi {{first_name}} - just checking whether this is relevant for {{custom.company}}.",
                        "isActive": true,
                        "order": 0
                      }
                    ]
                  }
                },
                {
                  "id": "aiCategorizer-1",
                  "type": "aiCategorizer",
                  "position": {
                    "x": 940,
                    "y": 0
                  },
                  "data": {
                    "label": "Categorizer",
                    "use_ai": true
                  }
                },
                {
                  "id": "email-3",
                  "type": "email",
                  "position": {
                    "x": 1180,
                    "y": -120
                  },
                  "data": {
                    "label": "Interested Reply",
                    "priority": true,
                    "variants": [
                      {
                        "id": "33333333-3333-4333-8333-333333333333",
                        "label": "A",
                        "subject": "",
                        "template": "Thanks {{first_name}} - here are the details you asked for.",
                        "isActive": true,
                        "order": 0
                      }
                    ]
                  }
                },
                {
                  "id": "email-4",
                  "type": "email",
                  "position": {
                    "x": 1180,
                    "y": 120
                  },
                  "data": {
                    "label": "Breakup",
                    "priority": true,
                    "variants": [
                      {
                        "id": "44444444-4444-4444-8444-444444444444",
                        "label": "A",
                        "subject": "Closing the loop, {{first_name}}",
                        "template": "No worries {{first_name}} - I’ll close the loop on my side.",
                        "isActive": true,
                        "order": 0
                      }
                    ]
                  }
                }
              ],
              "edges": [
                {
                  "id": "e1",
                  "source": "leadSource-1",
                  "target": "email-1"
                },
                {
                  "id": "e2",
                  "source": "email-1",
                  "target": "waitTime-1"
                },
                {
                  "id": "e3",
                  "source": "waitTime-1",
                  "target": "email-2"
                },
                {
                  "id": "e4",
                  "source": "email-2",
                  "target": "aiCategorizer-1"
                },
                {
                  "id": "e5",
                  "source": "aiCategorizer-1",
                  "sourceHandle": "interested",
                  "target": "email-3"
                },
                {
                  "id": "e6",
                  "source": "aiCategorizer-1",
                  "sourceHandle": "not-interested",
                  "target": "email-4"
                }
              ]
            }
          },
          "dataSender": {
            "summary": "Data sender webhook",
            "value": {
              "nodes": [
                {
                  "id": "leadSource-1",
                  "type": "leadSource",
                  "position": {
                    "x": 0,
                    "y": 0
                  },
                  "data": {
                    "label": "Lead Bucket",
                    "customFieldKeys": [
                      "company"
                    ],
                    "mappedStandardFieldKeys": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "isRequired": true
                  },
                  "deletable": false
                },
                {
                  "id": "email-1",
                  "type": "email",
                  "position": {
                    "x": 220,
                    "y": 0
                  },
                  "data": {
                    "label": "Intro Email",
                    "priority": false,
                    "variants": [
                      {
                        "id": "11111111-1111-4111-8111-111111111111",
                        "label": "A",
                        "subject": "Quick question for {{first_name}}",
                        "template": "Hi {{first_name}} - reaching out about {{custom.company}}.",
                        "isActive": true,
                        "order": 0
                      },
                      {
                        "id": "11111111-1111-4111-8111-111111111112",
                        "label": "B",
                        "subject": "Following up for {{first_name}}",
                        "template": "Hi {{first_name}} - wanted to share a quick idea for {{custom.company}}.",
                        "isActive": true,
                        "order": 1
                      }
                    ]
                  }
                },
                {
                  "id": "dataSender-1",
                  "type": "dataSender",
                  "position": {
                    "x": 460,
                    "y": 0
                  },
                  "data": {
                    "label": "Notify CRM",
                    "endpoint_url": "https://hooks.example.com/lead-contacted",
                    "payload": "{\n  \"email\": \"{{email}}\",\n  \"company\": \"{{custom.company}}\",\n  \"campaign_node\": \"email-1\"\n}",
                    "on_failure": "continue"
                  }
                }
              ],
              "edges": [
                {
                  "id": "e1",
                  "source": "leadSource-1",
                  "target": "email-1"
                },
                {
                  "id": "e2",
                  "source": "email-1",
                  "target": "dataSender-1"
                }
              ]
            }
          }
        }
      },
      "FlowPosition": {
        "type": "object",
        "description": "Builder canvas coordinates. Cosmetic; safe to change on live campaigns.",
        "properties": {
          "x": {
            "type": "number",
            "description": "Horizontal position in the flow editor.",
            "example": 220
          },
          "y": {
            "type": "number",
            "description": "Vertical position in the flow editor.",
            "example": 0
          }
        },
        "required": [
          "x",
          "y"
        ],
        "additionalProperties": false
      },
      "EmailVariant": {
        "type": "object",
        "description": "One A/B variant of an email node. Variant ids must be stable UUIDs. Supports merge variables in `subject`, `template`, and `body_html`.\n\nEmpty `subject` reuses the subject from the newest subject epoch and continues that conversation. An explicit non-empty `subject` starts a new conversation (no inherited reply headers).\n\nSee [Email sequences](/docs/concepts/sequences/).",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Stable variant UUID. Generate once before first save.",
            "example": "11111111-1111-4111-8111-111111111111"
          },
          "label": {
            "type": "string",
            "description": "Display label (A, B, …). Re-derived on save.",
            "example": "A"
          },
          "subject": {
            "type": "string",
            "description": "Email subject. Supports merge variables like {{first_name}}.",
            "example": "Quick question for {{first_name}}"
          },
          "template": {
            "type": "string",
            "description": "Primary email body (plain or rich text). Supports merge variables.",
            "example": "Hi {{first_name}} - reaching out about {{custom.company}}."
          },
          "body_html": {
            "type": "string",
            "nullable": true,
            "description": "HTML body when editor_mode is html."
          },
          "body_text": {
            "type": "string",
            "nullable": true,
            "description": "Plain-text fallback body."
          },
          "editor_mode": {
            "type": "string",
            "enum": [
              "richText",
              "html"
            ],
            "nullable": true,
            "description": "Editor mode. Canonicalized on save.",
            "example": "richText"
          },
          "isActive": {
            "type": "boolean",
            "description": "When false, variant is skipped in round-robin. At least one variant per email node must be active.",
            "example": true
          },
          "order": {
            "type": "integer",
            "description": "Round-robin sort order. Re-derived on save.",
            "example": 0
          }
        },
        "required": [
          "id",
          "label",
          "subject",
          "template",
          "isActive",
          "order"
        ],
        "additionalProperties": false
      },
      "FlowNode": {
        "type": "object",
        "description": "One node in the campaign flow graph. The data shape depends on type — see [LeadSourceNodeData](/docs/reference/schemas/LeadSourceNodeData/), [EmailNodeData](/docs/reference/schemas/EmailNodeData/), [WaitTimeNodeData](/docs/reference/schemas/WaitTimeNodeData/), [AICategorizerNodeData](/docs/reference/schemas/AICategorizerNodeData/), and [DataSenderNodeData](/docs/reference/schemas/DataSenderNodeData/).",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable flow node id referenced by edges and runtime node sync. Keep stable across edits.",
            "example": "email-1"
          },
          "type": {
            "type": "string",
            "enum": [
              "leadSource",
              "email",
              "waitTime",
              "aiCategorizer",
              "dataSender"
            ],
            "description": "Node kind. Exactly one leadSource per flow; at most one aiCategorizer.",
            "example": "email"
          },
          "position": {
            "$ref": "#/components/schemas/FlowPosition"
          },
          "data": {
            "description": "Type-specific node configuration.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/LeadSourceNodeData"
              },
              {
                "$ref": "#/components/schemas/EmailNodeData"
              },
              {
                "$ref": "#/components/schemas/WaitTimeNodeData"
              },
              {
                "$ref": "#/components/schemas/AICategorizerNodeData"
              },
              {
                "$ref": "#/components/schemas/DataSenderNodeData"
              }
            ]
          },
          "deletable": {
            "type": "boolean",
            "nullable": true,
            "description": "When false, node cannot be deleted in the builder. Lead source is always non-deletable.",
            "example": true
          }
        },
        "required": [
          "id",
          "type",
          "position",
          "data"
        ],
        "additionalProperties": false
      },
      "FlowEdge": {
        "type": "object",
        "description": "Directed connection between two nodes. Categorizer outgoing edges must set sourceHandle to interested, neutral, or not-interested.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable edge identifier.",
            "example": "e1"
          },
          "source": {
            "type": "string",
            "description": "Source node id.",
            "example": "leadSource-1"
          },
          "target": {
            "type": "string",
            "description": "Target node id.",
            "example": "email-1"
          },
          "sourceHandle": {
            "type": "string",
            "nullable": true,
            "description": "Required on aiCategorizer branch edges: interested, neutral, or not-interested.",
            "example": "interested"
          },
          "targetHandle": {
            "type": "string",
            "nullable": true,
            "description": "Reserved for future use."
          },
          "type": {
            "type": "string",
            "nullable": true,
            "description": "Builder edge type. Stripped on save when set to deletable."
          }
        },
        "required": [
          "id",
          "source",
          "target"
        ],
        "additionalProperties": false
      },
      "LeadSourceNodeData": {
        "type": "object",
        "description": "Configuration for the single required `leadSource` node. Declares merge variables and custom lead fields.\n\nAllowed standard keys for mappedStandardFieldKeys: `email`, `name`, `first_name`, `last_name`, `company_name`, `website`, `linkedin_url`, `company_linkedin_url`, `source`.\n\nDetails: [Email sequences](/docs/concepts/sequences/).",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label.",
            "example": "Lead Bucket"
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Legacy source label."
          },
          "bucketId": {
            "type": "string",
            "nullable": true,
            "description": "Optional lead bucket reference."
          },
          "customFieldKeys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Custom personalization keys. Enables {{custom.<key>}} merge tokens and requires matching keys in lead custom_lead_data on import.",
            "example": [
              "company",
              "title"
            ]
          },
          "mappedStandardFieldKeys": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Standard lead fields available as merge variables. When omitted, all standard fields are allowed.",
            "example": [
              "email",
              "first_name",
              "last_name"
            ]
          },
          "isRequired": {
            "type": "boolean",
            "nullable": true,
            "description": "When true, leads missing required custom fields count as incomplete on import.",
            "example": true
          }
        },
        "additionalProperties": false
      },
      "EmailNodeData": {
        "type": "object",
        "description": "Outbound email node with one or more A/B variants.\n\n`priority`: derived boolean (not user-set). True when the email is downstream of a categorizer and sends on the immediate/priority lane. See [EmailVariant](/docs/reference/schemas/EmailVariant/) for copy fields.",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label.",
            "example": "Intro Email"
          },
          "mailboxId": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Sending mailbox. Falls back to campaign mailbox rotation when unset."
          },
          "priority": {
            "type": "boolean",
            "nullable": true,
            "description": "Derived priority marker (not user-set). True when the email is downstream of a categorizer and sends on the immediate/priority lane.",
            "example": false
          },
          "variants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EmailVariant"
            },
            "description": "1–20 variants. At least one must be active.",
            "minItems": 1,
            "maxItems": 20
          }
        },
        "required": [
          "variants"
        ],
        "additionalProperties": false
      },
      "WaitTimeNodeData": {
        "type": "object",
        "description": "Delay node. `wait_duration_seconds` is the runtime source of truth; `duration` and `unit` are display fields derived on save.\nMinimum is `180` seconds (3 minutes). Empty, missing, or non-positive values normalize to `259200` (3 days).",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label.",
            "example": "Wait 3 days"
          },
          "duration": {
            "type": "string",
            "nullable": true,
            "description": "Display duration value. Furnace derives this from wait_duration_seconds on save.",
            "example": "3"
          },
          "unit": {
            "type": "string",
            "enum": [
              "minutes",
              "hours",
              "days"
            ],
            "nullable": true,
            "description": "Display unit. Furnace derives this from wait_duration_seconds on save.",
            "example": "days"
          },
          "wait_duration_seconds": {
            "type": "integer",
            "description": "Delay in seconds (runtime source of truth). Minimum 180 (3 minutes). Empty/missing values normalize to 259200 (3 days).",
            "example": 259200,
            "minimum": 180
          }
        },
        "required": [
          "wait_duration_seconds"
        ],
        "additionalProperties": false
      },
      "AICategorizerNodeData": {
        "type": "object",
        "description": "Reply classifier node. At most one per flow. Outgoing edges must use sourceHandle interested, neutral, or not-interested.",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label.",
            "example": "Categorizer"
          },
          "use_ai": {
            "type": "boolean",
            "description": "When true, uses AI to classify replies.",
            "example": true
          }
        },
        "additionalProperties": false
      },
      "DataSenderNodeData": {
        "type": "object",
        "description": "Webhook node that POSTs lead data to an external URL when a lead reaches this step. Supports merge variables in `payload`. See [CampaignFlow](/docs/reference/schemas/CampaignFlow/) examples for a full dataSender flow.",
        "properties": {
          "label": {
            "type": "string",
            "description": "Display label.",
            "example": "Notify CRM"
          },
          "endpoint": {
            "type": "string",
            "nullable": true,
            "description": "Alias for endpoint_url."
          },
          "endpoint_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "HTTPS webhook URL.",
            "example": "https://hooks.example.com/lead-contacted"
          },
          "payload": {
            "type": "string",
            "nullable": true,
            "description": "JSON string body. Supports merge variables.",
            "example": "{\"email\":\"{{email}}\",\"company\":\"{{custom.company}}\"}"
          },
          "payload_template": {
            "type": "object",
            "additionalProperties": true,
            "description": "Object form of payload. Serialized to payload on save when payload string is empty."
          },
          "on_failure": {
            "type": "string",
            "enum": [
              "continue",
              "stop"
            ],
            "nullable": true,
            "description": "Whether enrollment continues after a failed POST.",
            "example": "continue"
          }
        },
        "additionalProperties": false
      },
      "CampaignSchedule": {
        "type": "object",
        "description": "Campaign send window. Set the parent `schedule` field to `null` for 24/7 sending. On create, omitting `schedule` applies the product default (Central 9–5 Mon–Fri) rather than 24/7. `days_of_week` uses JS `Date.getDay()` (0=Sun … 6=Sat); null/empty means every day.",
        "properties": {
          "timezone": {
            "type": "string",
            "description": "IANA timezone, e.g. `America/Chicago`.",
            "example": "America/Chicago"
          },
          "start_hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23,
            "description": "Inclusive start hour in the campaign timezone.",
            "example": 9
          },
          "end_hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23,
            "description": "Exclusive end hour in the campaign timezone.",
            "example": 17
          },
          "days_of_week": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 6
            },
            "nullable": true,
            "description": "Allowed weekdays. Null/empty = every day.",
            "example": [
              1,
              2,
              3,
              4,
              5
            ]
          },
          "start_minute": {
            "type": "integer",
            "minimum": 0,
            "maximum": 59,
            "description": "Optional start minute. Defaults to 0 when omitted.",
            "example": 0
          },
          "end_minute": {
            "type": "integer",
            "minimum": 0,
            "maximum": 59,
            "description": "Optional end minute. Defaults to 0 when omitted.",
            "example": 0
          }
        },
        "required": [
          "timezone",
          "start_hour",
          "end_hour"
        ],
        "additionalProperties": false
      },
      "CampaignLifecycleSchedule": {
        "type": "object",
        "description": "Campaign calendar bounds. Dates are local calendar days in `time_zone`. `start_on` is the first sending day; `pause_on` is exclusive (sending stops before that local day). Empty `start_on` launches immediately; empty `pause_on` never auto-pauses.",
        "properties": {
          "time_zone": {
            "type": "string",
            "description": "IANA timezone used to interpret start_on and pause_on.",
            "example": "America/Chicago"
          },
          "start_on": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "First local sending date. Null means start as soon as the campaign is launched.",
            "example": "2026-09-01"
          },
          "pause_on": {
            "type": "string",
            "format": "date",
            "nullable": true,
            "description": "Exclusive local pause date. Null means the campaign never auto-pauses.",
            "example": "2026-10-01"
          },
          "start_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Read-only UTC instant of local midnight on start_on. Ignored on write.",
            "example": "2026-09-01T05:00:00.000Z"
          },
          "pause_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Read-only UTC instant of local midnight on pause_on. Ignored on write.",
            "example": "2026-10-01T05:00:00.000Z"
          }
        },
        "required": [
          "time_zone",
          "start_on",
          "pause_on"
        ],
        "additionalProperties": false
      },
      "CampaignCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignSchedule"
              }
            ],
            "nullable": true,
            "description": "Send window. Omit to use Central 9–5 Mon–Fri. Pass `null` for 24/7."
          },
          "sending_interval_seconds": {
            "type": "number",
            "description": "Seconds between sends per mailbox. Omit to use `1440` (24 minutes; ~20 emails per mailbox per day on the default window)."
          },
          "lifecycle_schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignLifecycleSchedule"
              }
            ],
            "nullable": true,
            "description": "Optional calendar start/pause dates. Omit to leave unset. `start_at`/`pause_at` are ignored on write."
          },
          "mailbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "flow": {
            "$ref": "#/components/schemas/CampaignFlow"
          }
        },
        "additionalProperties": false
      },
      "FlowUpdate": {
        "description": "Canonical campaign flow payload for `POST /v1/campaigns/{id}/flow`, `PUT .../flow` (deprecated), and `POST .../flow:validate`.\n\nSame shape as [CampaignFlow](/docs/reference/schemas/CampaignFlow/). See [Campaign setup](/docs/guides/campaign-setup/) and [Email sequences](/docs/concepts/sequences/).",
        "allOf": [
          {
            "$ref": "#/components/schemas/CampaignFlow"
          }
        ],
        "example": {
          "nodes": [
            {
              "id": "leadSource-1",
              "type": "leadSource",
              "position": {
                "x": 0,
                "y": 0
              },
              "data": {
                "label": "Lead Bucket",
                "customFieldKeys": [
                  "company"
                ],
                "mappedStandardFieldKeys": [
                  "email",
                  "first_name",
                  "last_name"
                ],
                "isRequired": true
              },
              "deletable": false
            },
            {
              "id": "email-1",
              "type": "email",
              "position": {
                "x": 220,
                "y": 0
              },
              "data": {
                "label": "Intro Email",
                "priority": false,
                "variants": [
                  {
                    "id": "11111111-1111-4111-8111-111111111111",
                    "label": "A",
                    "subject": "Quick question for {{first_name}}",
                    "template": "Hi {{first_name}} - reaching out about {{custom.company}}.",
                    "isActive": true,
                    "order": 0
                  },
                  {
                    "id": "11111111-1111-4111-8111-111111111112",
                    "label": "B",
                    "subject": "Following up for {{first_name}}",
                    "template": "Hi {{first_name}} - wanted to share a quick idea for {{custom.company}}.",
                    "isActive": true,
                    "order": 1
                  }
                ]
              }
            },
            {
              "id": "waitTime-1",
              "type": "waitTime",
              "position": {
                "x": 460,
                "y": 0
              },
              "data": {
                "label": "Wait 1 day",
                "duration": "1",
                "unit": "days",
                "wait_duration_seconds": 86400
              }
            },
            {
              "id": "email-2",
              "type": "email",
              "position": {
                "x": 700,
                "y": 0
              },
              "data": {
                "label": "Reply Trigger",
                "priority": false,
                "variants": [
                  {
                    "id": "22222222-2222-4222-8222-222222222221",
                    "label": "A",
                    "subject": "Checking back in, {{first_name}}",
                    "template": "Hi {{first_name}} - just checking whether this is relevant for {{custom.company}}.",
                    "isActive": true,
                    "order": 0
                  }
                ]
              }
            },
            {
              "id": "aiCategorizer-1",
              "type": "aiCategorizer",
              "position": {
                "x": 940,
                "y": 0
              },
              "data": {
                "label": "Categorizer",
                "use_ai": true
              }
            },
            {
              "id": "email-3",
              "type": "email",
              "position": {
                "x": 1180,
                "y": -120
              },
              "data": {
                "label": "Interested Reply",
                "priority": true,
                "variants": [
                  {
                    "id": "33333333-3333-4333-8333-333333333333",
                    "label": "A",
                    "subject": "",
                    "template": "Thanks {{first_name}} - here are the details you asked for.",
                    "isActive": true,
                    "order": 0
                  }
                ]
              }
            },
            {
              "id": "email-4",
              "type": "email",
              "position": {
                "x": 1180,
                "y": 120
              },
              "data": {
                "label": "Breakup",
                "priority": true,
                "variants": [
                  {
                    "id": "44444444-4444-4444-8444-444444444444",
                    "label": "A",
                    "subject": "Closing the loop, {{first_name}}",
                    "template": "No worries {{first_name}} - I’ll close the loop on my side.",
                    "isActive": true,
                    "order": 0
                  }
                ]
              }
            }
          ],
          "edges": [
            {
              "id": "e1",
              "source": "leadSource-1",
              "target": "email-1"
            },
            {
              "id": "e2",
              "source": "email-1",
              "target": "waitTime-1"
            },
            {
              "id": "e3",
              "source": "waitTime-1",
              "target": "email-2"
            },
            {
              "id": "e4",
              "source": "email-2",
              "target": "aiCategorizer-1"
            },
            {
              "id": "e5",
              "source": "aiCategorizer-1",
              "sourceHandle": "interested",
              "target": "email-3"
            },
            {
              "id": "e6",
              "source": "aiCategorizer-1",
              "sourceHandle": "not-interested",
              "target": "email-4"
            }
          ]
        }
      },
      "FlowValidationIssue": {
        "type": "object",
        "description": "One validation problem in `issues[]` from flow validate/save, or in `details[]` on `400 invalid_flow` errors.\n\nEach issue has a `path`, a `code`, and a human-readable `message` describing what to fix.",
        "properties": {
          "path": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "path",
          "code",
          "message"
        ],
        "additionalProperties": false
      },
      "FlowValidateResult": {
        "type": "object",
        "description": "Dry-run result from `POST /v1/campaigns/{id}/flow:validate`. Shows normalized flow, validation issues, change classification, and lifecycle gate outcome.\n\nSee [FlowValidationIssue](/docs/reference/schemas/FlowValidationIssue/).",
        "properties": {
          "normalized_flow": {
            "$ref": "#/components/schemas/CampaignFlow"
          },
          "allowed": {
            "type": "boolean",
            "description": "Whether the campaign status permits this change (false when structural edit on live campaign).",
            "example": true
          },
          "change_kind": {
            "type": "string",
            "enum": [
              "none",
              "content",
              "structural"
            ],
            "description": "Classification of the diff against the stored flow.",
            "example": "content"
          },
          "change_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Machine-readable change reasons: node_added, node_removed, node_type_changed, edge_added_or_rewired, edge_removed_or_rewired, variant_removed_or_replaced, content_changed.",
            "example": [
              "content_changed"
            ]
          },
          "lifecycle": {
            "type": "object",
            "description": "Lifecycle gate result. When blocked, code is flow_locked.",
            "properties": {
              "allowed": {
                "type": "boolean",
                "example": true
              },
              "code": {
                "type": "string",
                "nullable": true,
                "example": "flow_locked"
              },
              "message": {
                "type": "string",
                "nullable": true
              }
            },
            "required": [
              "allowed"
            ],
            "additionalProperties": false
          },
          "issues": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowValidationIssue"
            },
            "description": "Validation problems. Empty when the flow is valid."
          }
        },
        "required": [
          "normalized_flow",
          "allowed",
          "change_kind",
          "change_reasons",
          "lifecycle",
          "issues"
        ],
        "additionalProperties": false
      },
      "LaunchResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "scheduled"
            ]
          },
          "enrolled": {
            "type": "integer",
            "description": "Number of leads enrolled at launch."
          },
          "lifecycle_schedule": {
            "$ref": "#/components/schemas/CampaignLifecycleSchedule"
          }
        },
        "required": [
          "id",
          "status"
        ],
        "additionalProperties": false
      },
      "CampaignStatusUpdate": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "running",
              "paused",
              "stopped"
            ]
          }
        },
        "required": [
          "status"
        ],
        "additionalProperties": false
      },
      "FieldSync": {
        "type": "object",
        "properties": {
          "declared_custom_added": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "declared_standard_added": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "declared_custom_added",
          "declared_standard_added"
        ],
        "additionalProperties": false
      },
      "FlowSaveResult": {
        "type": "object",
        "properties": {
          "flow": {
            "$ref": "#/components/schemas/CampaignFlow"
          },
          "flow_revision": {
            "type": "string",
            "description": "SHA-256 of canonical normalized flow."
          },
          "field_sync": {
            "$ref": "#/components/schemas/FieldSync"
          },
          "change_kind": {
            "type": "string",
            "enum": [
              "none",
              "content",
              "structural"
            ]
          },
          "change_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "reactivated_count": {
            "type": "integer",
            "description": "Completed enrollments reactivated on non-categorizer nodes with a live outgoing edge after a flow save."
          }
        },
        "required": [
          "flow",
          "flow_revision",
          "field_sync",
          "reactivated_count"
        ],
        "additionalProperties": false
      },
      "FlowNodePatch": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "CampaignUpdate": {
        "type": "object",
        "description": "Mutable campaign fields. Mailbox ids can replace the full set or be incrementally added and removed.",
        "properties": {
          "name": {
            "type": "string"
          },
          "schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignSchedule"
              }
            ],
            "nullable": true,
            "description": "Send window. `null` means send 24/7."
          },
          "sending_interval_seconds": {
            "type": "number"
          },
          "lifecycle_schedule": {
            "allOf": [
              {
                "$ref": "#/components/schemas/CampaignLifecycleSchedule"
              }
            ],
            "nullable": true,
            "description": "Replace the campaign calendar bounds. Omitted leaves the current dates unchanged. `null` clears start_on and pause_on. `start_at`/`pause_at` are ignored on write."
          },
          "mailbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "add_mailbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "remove_mailbox_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Replace all tag assignments on the campaign."
          },
          "add_tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "remove_tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "additionalProperties": false
      },
      "CampaignStatusResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "paused",
              "stopped",
              "running"
            ]
          }
        },
        "required": [
          "id",
          "status"
        ]
      },
      "LeadFields": {
        "type": "object",
        "properties": {
          "standard": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "custom": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "standard",
          "custom"
        ]
      },
      "LeadFieldCreate": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          }
        },
        "required": [
          "key"
        ]
      },
      "LeadFieldResult": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          }
        },
        "required": [
          "key"
        ]
      },
      "Lead": {
        "type": "object",
        "description": "Lead row scoped to a campaign.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "global_lead_id": {
            "type": "string",
            "description": "Stable account-scoped person id (SHA-256 of normalized email). Used for enrollment pause/resume and bulk membership APIs."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "company_name": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "company_linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          },
          "mobile_phone_number": {
            "type": "string",
            "nullable": true
          },
          "custom_lead_data": {
            "type": "object",
            "additionalProperties": true
          },
          "source": {
            "type": "string",
            "examples": [
              "api"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "campaign_id",
          "email",
          "created_at"
        ],
        "additionalProperties": false
      },
      "LeadCreate": {
        "type": "object",
        "description": "Create or upsert a lead. `email` is required. When the campaign defines custom lead fields, every key must be present in `custom_lead_data`.",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "company_name": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "linkedin_url": {
            "type": "string"
          },
          "company_linkedin_url": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          },
          "mobile_phone_number": {
            "type": "string"
          },
          "custom_lead_data": {
            "type": "object",
            "additionalProperties": true
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional person-level tags. Pass catalog names or aliases (for example `Hunter`, `Hunter.io`, `Running Meta Ads`) or any custom name. Matching is case-insensitive. Unknown names create an account-owned tag. Tags attach to the person (`global_lead_id`), not the campaign lead row, so they persist across campaigns. Do not put MillionVerifier statuses here — use `email_verification`. Catch-All Domain and Role Account are operator filters and are not auto-applied from verification."
          },
          "email_verification": {
            "type": "object",
            "additionalProperties": false,
            "description": "Optional structured email verification from a vendor such as MillionVerifier. Send this when you already paid for a check; omit it otherwise. Status values: `ok`, `catch_all`, `invalid`, `unknown`, `disposable`. Stored on `lead_email_facts`, not as tags, and survives rollup refresh. Do not invent a status.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ok",
                  "catch_all",
                  "invalid",
                  "unknown",
                  "disposable"
                ]
              },
              "quality": {
                "type": "string"
              },
              "provider": {
                "type": "string"
              },
              "verified_at": {
                "type": "string",
                "format": "date-time"
              },
              "is_free": {
                "type": "boolean"
              },
              "is_role": {
                "type": "boolean"
              }
            }
          }
        },
        "required": [
          "email"
        ],
        "additionalProperties": false
      },
      "LeadUpdate": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "company_name": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "company_linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          },
          "mobile_phone_number": {
            "type": "string",
            "nullable": true
          },
          "custom_lead_data": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "additionalProperties": false
      },
      "LeadUpsertResult": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Lead"
          },
          "created": {
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "created"
        ]
      },
      "BulkLeadsRequest": {
        "type": "object",
        "properties": {
          "leads": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/LeadCreate"
            }
          }
        },
        "required": [
          "leads"
        ]
      },
      "AsyncBulkLeadsRequest": {
        "type": "object",
        "properties": {
          "leads": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/LeadCreate"
            }
          }
        },
        "required": [
          "leads"
        ]
      },
      "BulkLeadsResult": {
        "type": "object",
        "properties": {
          "imported": {
            "type": "integer"
          },
          "incomplete": {
            "type": "integer",
            "description": "Leads imported but missing one or more required custom (personalization) fields."
          },
          "failed": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "index",
                "message"
              ]
            }
          }
        },
        "required": [
          "imported",
          "incomplete",
          "failed",
          "errors"
        ]
      },
      "ImportJobError": {
        "type": "object",
        "description": "Per-item error recorded on an async import/membership job.",
        "properties": {
          "globalLeadId": {
            "type": "string",
            "nullable": true,
            "description": "Person id when the failure is scoped to a global lead (camelCase as emitted by RPCs)."
          },
          "index": {
            "type": "integer",
            "description": "Optional array index for lead-import errors."
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "additionalProperties": false
      },
      "ImportJobResult": {
        "type": "object",
        "description": "Aggregated counts written when a job completes. Which fields are populated depends on `input.operation` (e.g. import/add use created/updated/enrolled; remove uses removed; pause/resume use paused/resumed).",
        "properties": {
          "created": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          },
          "enrolled": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "incomplete": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "paused": {
            "type": "integer"
          },
          "resumed": {
            "type": "integer"
          },
          "removed": {
            "type": "integer"
          },
          "added": {
            "type": "integer"
          },
          "rows_exported": {
            "type": "integer"
          },
          "imported": {
            "type": "integer",
            "description": "Convenience total (`created + updated`) set on lead-import completion."
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportJobError"
            }
          }
        },
        "additionalProperties": false
      },
      "ImportJobInput": {
        "type": "object",
        "description": "Stored job payload. Uses `saved_list_id` when scoped to a list (the create request field is `list_id`). Includes `operation` plus scope fields (`global_lead_ids`, `saved_list_id`, `source_campaign_id`, `leads`, `exclusions`, etc.).",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "api_lead_import",
              "add_to_campaign",
              "remove_from_campaign",
              "remove_from_all_campaigns",
              "pause_enrollments",
              "resume_enrollments",
              "add_to_lead_list",
              "remove_from_lead_list",
              "export_leads",
              "csv_lead_import_staged"
            ]
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "saved_list_id": {
            "type": "string",
            "format": "uuid"
          },
          "source_campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "target_list_id": {
            "type": "string",
            "format": "uuid"
          },
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "list_id": {
            "type": "string",
            "format": "uuid"
          },
          "leads": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadCreate"
            }
          },
          "total_count": {
            "type": "integer"
          },
          "source": {
            "type": "string"
          },
          "exclusions": {
            "$ref": "#/components/schemas/BulkExclusions"
          },
          "preview_id": {
            "type": "string"
          },
          "expected_count": {
            "type": "integer"
          },
          "projection": {
            "type": "string",
            "enum": [
              "full",
              "compact"
            ]
          },
          "query": {
            "type": "object",
            "additionalProperties": true
          },
          "column_layout": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "filename_base": {
            "type": "string"
          }
        },
        "required": [
          "operation"
        ],
        "additionalProperties": true
      },
      "ImportJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "created_by_api_key_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "uploading",
              "queued",
              "running",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "progress": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "cursor": {
            "type": "integer",
            "minimum": 0
          },
          "input": {
            "$ref": "#/components/schemas/ImportJobInput"
          },
          "result": {
            "$ref": "#/components/schemas/ImportJobResult"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ImportJobError"
            }
          },
          "cancel_requested_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "input",
          "result",
          "errors"
        ],
        "additionalProperties": false
      },
      "ImportJobCreate": {
        "type": "object",
        "description": "Create one logical async bulk job. Prefer `scope` (+ optional `exclusions`) over inline ID batches. Poll `GET /v1/jobs/{id}`; cancel with `POST /v1/jobs/{id}/cancel`.",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "api_lead_import",
              "add_to_campaign",
              "remove_from_campaign",
              "remove_from_all_campaigns",
              "pause_enrollments",
              "resume_enrollments",
              "add_to_lead_list",
              "remove_from_lead_list",
              "export_leads",
              "csv_lead_import_staged"
            ]
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "list_id": {
            "type": "string",
            "format": "uuid"
          },
          "target_list_id": {
            "type": "string",
            "format": "uuid"
          },
          "source_campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "scope": {
            "$ref": "#/components/schemas/BulkScope"
          },
          "exclusions": {
            "$ref": "#/components/schemas/BulkExclusions"
          },
          "preview_id": {
            "type": "string"
          },
          "expected_count": {
            "type": "integer"
          },
          "projection": {
            "type": "string",
            "enum": [
              "full",
              "compact"
            ]
          },
          "filename_base": {
            "type": "string"
          },
          "column_layout": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "leads": {
            "type": "array",
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/LeadCreate"
            }
          }
        },
        "required": [
          "operation"
        ],
        "additionalProperties": false
      },
      "BulkScope": {
        "type": "object",
        "description": "Server-side population selector. Prefer list/campaign/staged scopes for bulk work.",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "selection",
              "explorer_view",
              "saved_list",
              "saved_list_filtered",
              "campaign",
              "staged_upload"
            ]
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "list_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "upload_id": {
            "type": "string",
            "format": "uuid"
          },
          "query": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "kind"
        ],
        "additionalProperties": false
      },
      "BulkExclusions": {
        "type": "object",
        "description": "People to exclude from a scoped bulk mutation.",
        "properties": {
          "list_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          }
        },
        "additionalProperties": false
      },
      "BulkPreviewRequest": {
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": [
              "api_lead_import",
              "add_to_campaign",
              "remove_from_campaign",
              "remove_from_all_campaigns",
              "pause_enrollments",
              "resume_enrollments",
              "add_to_lead_list",
              "remove_from_lead_list",
              "export_leads",
              "csv_lead_import_staged"
            ]
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "target_list_id": {
            "type": "string",
            "format": "uuid"
          },
          "list_id": {
            "type": "string",
            "format": "uuid"
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scope": {
            "$ref": "#/components/schemas/BulkScope"
          },
          "exclusions": {
            "$ref": "#/components/schemas/BulkExclusions"
          }
        },
        "required": [
          "operation"
        ],
        "additionalProperties": false
      },
      "BulkPreviewResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "preview_id": {
                "type": "string"
              },
              "operation": {
                "type": "string"
              },
              "operation_hash": {
                "type": "string"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              },
              "counts": {
                "type": "object",
                "properties": {
                  "matched": {
                    "type": "integer"
                  },
                  "excluded": {
                    "type": "integer"
                  },
                  "duplicate": {
                    "type": "integer"
                  },
                  "ineligible": {
                    "type": "integer"
                  },
                  "actionable": {
                    "type": "integer"
                  }
                },
                "required": [
                  "matched",
                  "excluded",
                  "duplicate",
                  "ineligible",
                  "actionable"
                ]
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "scope": {
                "$ref": "#/components/schemas/BulkScope"
              },
              "exclusions": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/BulkExclusions"
                  }
                ],
                "nullable": true
              },
              "target": {
                "type": "object",
                "additionalProperties": true
              }
            },
            "required": [
              "preview_id",
              "operation",
              "operation_hash",
              "expires_at",
              "counts",
              "warnings",
              "scope"
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "StagedImportCreateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ImportJob"
          }
        },
        "required": [
          "data"
        ]
      },
      "StagedImportAppendRequest": {
        "type": "object",
        "properties": {
          "leads": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "$ref": "#/components/schemas/LeadCreate"
            }
          }
        },
        "required": [
          "leads"
        ],
        "additionalProperties": false
      },
      "StagedImportAppendResponse": {
        "type": "object",
        "properties": {
          "uploaded_count": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "uploaded_count",
          "total_count"
        ]
      },
      "BulkUploadCreateRequest": {
        "type": "object",
        "properties": {
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "filename": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          }
        },
        "required": [
          "campaign_id"
        ],
        "additionalProperties": false
      },
      "BulkUploadCreateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "upload_id": {
                "type": "string",
                "format": "uuid"
              },
              "upload_url": {
                "type": "string",
                "format": "uri"
              },
              "expires_at": {
                "type": "string",
                "format": "date-time"
              },
              "filename": {
                "type": "string"
              },
              "content_type": {
                "type": "string"
              }
            },
            "required": [
              "upload_id",
              "upload_url",
              "expires_at"
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "LimitsGuideResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LimitsGuide"
          }
        },
        "required": [
          "data"
        ]
      },
      "Mailbox": {
        "type": "object",
        "description": "Mailbox row with sensitive IMAP/SMTP passwords removed from the response.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "display_name": {
            "type": "string",
            "nullable": true
          },
          "provider": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "tags": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MailboxTag"
            },
            "description": "Mailbox tags assigned to this mailbox."
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      },
      "MailboxTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "created_at"
        ]
      },
      "MailboxTagCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "MailboxTagUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "MailboxTagResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MailboxTag"
          }
        },
        "required": [
          "data"
        ]
      },
      "MailboxTagListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MailboxTag"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "MailboxUpdate": {
        "type": "object",
        "description": "Mutable mailbox fields currently support tag assignment only.",
        "properties": {
          "tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Replace all tag assignments on the mailbox."
          },
          "add_tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "remove_tag_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        },
        "additionalProperties": false
      },
      "Thread": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "mailbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "last_message_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Latest activity in either direction (sent or received)."
          },
          "last_inbound_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Latest inbound lead reply. Used for inbox Newest/Oldest sort and date filters."
          }
        },
        "required": [
          "id",
          "account_id"
        ],
        "additionalProperties": false
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "direction": {
            "type": "string",
            "enum": [
              "sent",
              "received"
            ]
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "body_text": {
            "type": "string",
            "nullable": true
          },
          "body_html": {
            "type": "string",
            "nullable": true
          },
          "from_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "from_name": {
            "type": "string",
            "nullable": true
          },
          "to_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "to_name": {
            "type": "string",
            "nullable": true
          },
          "to_emails": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "nullable": true,
            "description": "All To addresses when known. to_email remains the primary/first recipient."
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "nullable": true
          },
          "received_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "thread_id"
        ],
        "additionalProperties": false
      },
      "ReplyRequest": {
        "type": "object",
        "description": "Create a reply job for a thread message. When omitted, subject and recipient fields fall back to the target message.",
        "properties": {
          "in_reply_to_message_id": {
            "type": "string",
            "format": "uuid",
            "description": "Message to reply to. Defaults to the latest message in the thread."
          },
          "subject": {
            "type": "string"
          },
          "body_text": {
            "type": "string"
          },
          "body_html": {
            "type": "string"
          },
          "to_email": {
            "type": "string",
            "format": "email"
          },
          "to_name": {
            "type": "string"
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          }
        },
        "additionalProperties": false
      },
      "ForwardRequest": {
        "type": "object",
        "description": "Create a forward job for a specific message in the thread.",
        "properties": {
          "forward_message_id": {
            "type": "string",
            "format": "uuid"
          },
          "subject": {
            "type": "string"
          },
          "body_text": {
            "type": "string"
          },
          "body_html": {
            "type": "string"
          },
          "to_email": {
            "type": "string",
            "format": "email"
          },
          "to_name": {
            "type": "string"
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          }
        },
        "required": [
          "forward_message_id",
          "to_email"
        ],
        "additionalProperties": false
      },
      "ThreadUpdate": {
        "type": "object",
        "description": "Partial thread update. All fields are optional.",
        "properties": {
          "category": {
            "type": "string",
            "nullable": true,
            "enum": [
              "Interested",
              "Neutral",
              "Not Interested",
              "Auto Reply",
              null
            ]
          },
          "conversation_status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "read": {
            "type": "boolean",
            "description": "When true, marks all received messages in the thread as read."
          }
        },
        "additionalProperties": false
      },
      "MessageJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "message_type": {
            "type": "string",
            "nullable": true
          },
          "thread_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "error_message": {
            "type": "string",
            "nullable": true
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "send_wait_reason": {
            "type": "string",
            "nullable": true
          },
          "status_reason": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status"
        ],
        "additionalProperties": false
      },
      "OutOfOfficeUpdate": {
        "type": "object",
        "properties": {
          "resume_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "resume_mode": {
            "type": "string",
            "enum": [
              "scheduled",
              "instant",
              "none"
            ],
            "default": "scheduled"
          }
        },
        "additionalProperties": false
      },
      "OutOfOfficeResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "thread": {
                "$ref": "#/components/schemas/Thread"
              },
              "result": {
                "type": "string"
              }
            },
            "required": [
              "thread",
              "result"
            ]
          }
        },
        "required": [
          "data"
        ]
      },
      "ReplaceLeadRequest": {
        "type": "object",
        "properties": {
          "new_email": {
            "type": "string",
            "format": "email"
          },
          "new_name": {
            "type": "string",
            "nullable": true
          },
          "new_first_name": {
            "type": "string",
            "nullable": true
          },
          "new_last_name": {
            "type": "string",
            "nullable": true
          },
          "new_phone_number": {
            "type": "string",
            "nullable": true
          },
          "new_mobile_phone_number": {
            "type": "string",
            "nullable": true
          },
          "reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "auto_reply_forward",
              "manual_referral",
              "wrong_contact",
              "role_change",
              "other"
            ],
            "description": "Defaults to manual_referral when omitted."
          },
          "reason_note": {
            "type": "string",
            "nullable": true
          },
          "source_message_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "forward_message_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "new_email"
        ],
        "additionalProperties": false
      },
      "ReplaceLeadResult": {
        "type": "object",
        "properties": {
          "replacement_id": {
            "type": "string",
            "format": "uuid"
          },
          "new_lead_id": {
            "type": "string",
            "format": "uuid"
          },
          "enrollment_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "mode": {
            "type": "string",
            "enum": [
              "created",
              "attached"
            ],
            "description": "created = a new lead was inserted and the original archived. attached = the address was already a live lead in this campaign, so that contact was reused, the conversation was moved to them, and the original lead was retired as stopped/replaced. new_lead_id is the pre-existing contact in that case."
          },
          "target_lead_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "On mode = attached, the pre-existing campaign contact that was reused. Null on mode = created."
          },
          "retired_sibling_count": {
            "type": "integer",
            "description": "Only non-zero on mode = attached. How many duplicate lead rows for the same address had their sequence stopped."
          },
          "forward_job_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          }
        },
        "required": [
          "replacement_id",
          "new_lead_id"
        ]
      },
      "ReplaceLeadPreviewLead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "phone_number": {
            "type": "string",
            "nullable": true
          },
          "mobile_phone_number": {
            "type": "string",
            "nullable": true
          },
          "company_name": {
            "type": "string",
            "nullable": true
          },
          "website": {
            "type": "string",
            "nullable": true
          },
          "linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "company_linkedin_url": {
            "type": "string",
            "nullable": true
          },
          "custom_lead_data": {
            "type": "object",
            "additionalProperties": true
          },
          "enrollment_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "enrollment_state": {
            "type": "string",
            "nullable": true,
            "enum": [
              "active",
              "paused",
              "completed",
              "stopped"
            ]
          },
          "has_been_contacted": {
            "type": "boolean"
          },
          "last_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "has_been_contacted",
          "custom_lead_data"
        ],
        "additionalProperties": false
      },
      "ReplaceLeadPreview": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "nullable": true
          },
          "mode": {
            "type": "string",
            "enum": [
              "created",
              "attached"
            ],
            "description": "What POST /v1/threads/{id}/replace-lead would do: created when no live campaign match, attached when an existing contact would be reused."
          },
          "allowed": {
            "type": "boolean",
            "description": "False when the write path would refuse this email. See disallowed_reason."
          },
          "disallowed_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "same_as_current_lead",
              "target_missing_enrollment"
            ],
            "description": "Same error codes the write path returns: same_as_current_lead (400) or target_missing_enrollment (409). Null when allowed."
          },
          "match_count": {
            "type": "integer",
            "description": "How many live campaign lead rows match this address (excluding the current thread lead)."
          },
          "matches_current_lead": {
            "type": "boolean"
          },
          "blocked": {
            "type": "boolean",
            "description": "True when the address or its domain is on the account block list. Does not by itself block replace; it is a warning for the caller."
          },
          "block_reason": {
            "type": "string",
            "nullable": true
          },
          "existing_lead": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ReplaceLeadPreviewLead"
              }
            ],
            "nullable": true
          }
        },
        "required": [
          "mode",
          "allowed",
          "match_count",
          "matches_current_lead",
          "blocked",
          "existing_lead"
        ],
        "additionalProperties": false
      },
      "ReplaceLeadPreviewResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ReplaceLeadPreview"
          }
        },
        "required": [
          "data"
        ]
      },
      "ThreadTag": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "color": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "account_id",
          "name"
        ],
        "additionalProperties": false
      },
      "ThreadTagAssignmentRequest": {
        "type": "object",
        "properties": {
          "tag_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "tag_id"
        ],
        "additionalProperties": false
      },
      "ThreadTagAssignmentResult": {
        "type": "object",
        "properties": {
          "thread_id": {
            "type": "string",
            "format": "uuid"
          },
          "tag_id": {
            "type": "string",
            "format": "uuid"
          },
          "removed": {
            "type": "boolean"
          }
        },
        "required": [
          "thread_id",
          "tag_id"
        ]
      },
      "ReplyJobResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id"
        ]
      },
      "BlockListEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "value": {
            "type": "string",
            "description": "Email address when `type` is `email`, or the exact host when `type` is `domain` (`example.com`)."
          },
          "type": {
            "type": "string",
            "enum": [
              "email",
              "domain"
            ],
            "description": "`email` matches one address. `domain` matches every address whose host equals `value` (not subdomains)."
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "account_id",
          "value",
          "type"
        ],
        "additionalProperties": false
      },
      "BlockListCreate": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "description": "Email address when `type` is `email`, or the host only when `type` is `domain` (`example.com`, not `@example.com`)."
          },
          "type": {
            "type": "string",
            "enum": [
              "email",
              "domain"
            ],
            "description": "`email` blocks one address. `domain` blocks every address at that exact host (`pat@example.com`, not `pat@mail.example.com`)."
          },
          "reason": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "value",
          "type"
        ],
        "additionalProperties": false
      },
      "CampaignStatsDaily": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "sent": {
            "type": "number"
          },
          "replied": {
            "type": "number"
          },
          "positiveReply": {
            "type": "number"
          },
          "bounce": {
            "type": "number"
          }
        },
        "required": [
          "date",
          "sent",
          "replied",
          "positiveReply",
          "bounce"
        ]
      },
      "CampaignStatsTotals": {
        "type": "object",
        "properties": {
          "sentCount": {
            "type": "number"
          },
          "repliedCount": {
            "type": "number"
          },
          "positiveReplyCount": {
            "type": "number"
          },
          "bounceCount": {
            "type": "number"
          },
          "lastBounceAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "enrollmentCount": {
            "type": "integer"
          },
          "terminalEnrollmentCount": {
            "type": "integer"
          },
          "contactedEnrollmentCount": {
            "type": "integer"
          }
        },
        "required": [
          "sentCount",
          "repliedCount",
          "positiveReplyCount",
          "bounceCount",
          "lastBounceAt",
          "enrollmentCount",
          "terminalEnrollmentCount",
          "contactedEnrollmentCount"
        ]
      },
      "CampaignStats": {
        "type": "object",
        "properties": {
          "daily": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CampaignStatsDaily"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CampaignStatsTotals"
          }
        },
        "required": [
          "daily",
          "totals"
        ]
      },
      "CampaignListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Campaign"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "CampaignResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Campaign"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignCreateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Campaign"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignFlowResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignFlow"
          }
        },
        "required": [
          "data"
        ]
      },
      "FlowSaveResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/FlowSaveResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "FlowRevisionConflictError": {
        "type": "object",
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ApiError"
          },
          "current_flow_revision": {
            "type": "string"
          }
        },
        "required": [
          "error",
          "current_flow_revision"
        ]
      },
      "FlowTemplatesResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "description": {
                  "type": "string"
                },
                "flow": {
                  "$ref": "#/components/schemas/CampaignFlow"
                }
              },
              "required": [
                "id",
                "name",
                "description",
                "flow"
              ]
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "FlowValidateResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/FlowValidateResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignStatusResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignStatusResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "LaunchResponseEnvelope": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LaunchResponse"
          }
        },
        "required": [
          "data"
        ]
      },
      "PauseEnrollmentsRequest": {
        "type": "object",
        "properties": {
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          }
        },
        "required": [
          "global_lead_ids"
        ]
      },
      "ResumeEnrollmentsRequest": {
        "type": "object",
        "properties": {
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1
          }
        },
        "required": [
          "global_lead_ids"
        ]
      },
      "EnrollmentActionResult": {
        "type": "object",
        "properties": {
          "paused": {
            "type": "integer"
          },
          "resumed": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      },
      "EnrollmentActionResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/EnrollmentActionResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "LeadFieldsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LeadFields"
          }
        },
        "required": [
          "data"
        ]
      },
      "LeadFieldResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LeadFieldResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "LeadListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Lead"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "LeadResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Lead"
          }
        },
        "required": [
          "data"
        ]
      },
      "DeleteResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/DeleteResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "ImportJobResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ImportJob"
          }
        },
        "required": [
          "data"
        ]
      },
      "MailboxListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Mailbox"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "MailboxResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Mailbox"
          }
        },
        "required": [
          "data"
        ]
      },
      "ThreadListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Thread"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "ThreadResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Thread"
          }
        },
        "required": [
          "data"
        ]
      },
      "MessageListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Message"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "GlobalLeadIdsRequest": {
        "type": "object",
        "properties": {
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": [
          "global_lead_ids"
        ],
        "additionalProperties": false
      },
      "MembershipActionError": {
        "type": "object",
        "description": "Per-item error from a sync membership RPC.",
        "properties": {
          "globalLeadId": {
            "type": "string",
            "nullable": true,
            "description": "Person id when the failure is scoped to a global lead (camelCase as emitted by RPCs)."
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "MembershipAddResult": {
        "type": "object",
        "description": "Counts from `add_global_leads_to_campaign`.",
        "properties": {
          "created": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          },
          "enrolled": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "incomplete": {
            "type": "integer"
          },
          "failed": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MembershipActionError"
            }
          }
        },
        "required": [
          "created",
          "updated",
          "enrolled",
          "skipped",
          "incomplete",
          "failed",
          "errors"
        ],
        "additionalProperties": false
      },
      "MembershipRemoveResult": {
        "type": "object",
        "description": "Counts from remove-membership RPCs.",
        "properties": {
          "removed": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MembershipActionError"
            }
          }
        },
        "required": [
          "removed",
          "skipped",
          "errors"
        ],
        "additionalProperties": false
      },
      "MembershipAddResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MembershipAddResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "MembershipRemoveResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MembershipRemoveResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "Person": {
        "type": "object",
        "description": "Account-scoped person rollup. List and detail share one shape (`latest_activity_at`). Detail/PATCH responses may also include `account_id`, rollup counts, and `updated_at`.",
        "properties": {
          "global_lead_id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "display_name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "campaign_count": {
            "type": "integer"
          },
          "company_list": {
            "type": "string",
            "nullable": true
          },
          "has_reply": {
            "type": "boolean"
          },
          "latest_activity_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "newest_membership_created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "native_campaign_count": {
            "type": "integer"
          },
          "smartlead_campaign_count": {
            "type": "integer"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "global_lead_id",
          "campaign_count",
          "has_reply"
        ],
        "additionalProperties": false
      },
      "PersonMembership": {
        "type": "object",
        "description": "Minimal campaign membership slice for a person (`leads` row). `deleted_at` null means the membership is active.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "nullable": true
          },
          "deleted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "campaign_id",
          "created_at"
        ],
        "additionalProperties": false
      },
      "PersonUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true
          },
          "first_name": {
            "type": "string",
            "nullable": true
          },
          "last_name": {
            "type": "string",
            "nullable": true
          },
          "company_name": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "PersonResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Person"
          }
        },
        "required": [
          "data"
        ]
      },
      "PersonDetailResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "person": {
                "$ref": "#/components/schemas/Person"
              },
              "memberships": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PersonMembership"
                }
              }
            },
            "required": [
              "person",
              "memberships"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "data"
        ]
      },
      "PersonListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Person"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "LeadSavedList": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "column_layout": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name"
        ],
        "additionalProperties": false
      },
      "LeadSavedListCreate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name"
        ],
        "additionalProperties": false
      },
      "LeadSavedListUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "column_layout": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "additionalProperties": false
      },
      "LeadSavedListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LeadSavedList"
          }
        },
        "required": [
          "data"
        ]
      },
      "LeadSavedListArrayResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadSavedList"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "LeadListMembersResult": {
        "type": "object",
        "properties": {
          "added": {
            "type": "integer"
          },
          "removed": {
            "type": "integer"
          },
          "skippedAlreadyMember": {
            "type": "integer"
          },
          "skippedNotMember": {
            "type": "integer"
          }
        },
        "additionalProperties": false
      },
      "LeadListMembersResultResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LeadListMembersResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "BatchCompletionWebhookPayload": {
        "type": "object",
        "description": "Standard payload for async or sync bulk completion webhooks.",
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "source": {
            "type": "string",
            "enum": [
              "async",
              "sync"
            ]
          },
          "campaign_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "operation": {
            "type": "string",
            "enum": [
              "api_lead_import",
              "add_to_campaign",
              "remove_from_campaign",
              "remove_from_all_campaigns",
              "pause_enrollments",
              "resume_enrollments",
              "add_to_lead_list",
              "remove_from_lead_list",
              "export_leads",
              "csv_lead_import_staged"
            ]
          },
          "counts": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "global_lead_id": {
                  "type": "string"
                },
                "index": {
                  "type": "integer"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "message"
              ]
            }
          },
          "global_lead_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "job_id",
          "source",
          "campaign_id",
          "operation",
          "counts",
          "errors"
        ]
      },
      "ReplyJobResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ReplyJobResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "MessageJobResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MessageJob"
          }
        },
        "required": [
          "data"
        ]
      },
      "ThreadTagListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThreadTag"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "ThreadTagAssignmentResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ThreadTagAssignmentResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "ReplaceLeadResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ReplaceLeadResult"
          }
        },
        "required": [
          "data"
        ]
      },
      "BlockListListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BlockListEntry"
            }
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "total_count": {
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ]
      },
      "BlockListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/BlockListEntry"
          }
        },
        "required": [
          "data"
        ]
      },
      "CampaignStatsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CampaignStats"
          }
        },
        "required": [
          "data"
        ]
      },
      "WebhookSettings": {
        "type": "object",
        "properties": {
          "webhook_url": {
            "type": "string",
            "nullable": true
          },
          "webhook_signing_secret": {
            "type": "string",
            "nullable": true
          },
          "webhook_enabled_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "WebhookSettingsUpdate": {
        "type": "object",
        "properties": {
          "webhook_url": {
            "type": "string",
            "nullable": true
          },
          "webhook_signing_secret": {
            "type": "string",
            "nullable": true
          },
          "webhook_enabled_events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "WebhookSettingsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebhookSettings"
          }
        },
        "required": [
          "data"
        ]
      },
      "ApiKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "secret_prefix": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "revoked_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "ApiKeyCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ApiKeyWithSecret": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ApiKey"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "Full API key secret. Returned only on create."
              }
            },
            "required": [
              "secret"
            ]
          }
        ]
      },
      "ApiKeyListResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKey"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "ApiKeyResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ApiKey"
          }
        },
        "required": [
          "data"
        ]
      },
      "ApiKeyCreatedResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/ApiKeyWithSecret"
          }
        },
        "required": [
          "data"
        ]
      },
      "MailboxConnectSession": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "expired",
              "failed"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "mailbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "connect_url": {
            "type": "string",
            "format": "uri"
          },
          "error_message": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "MailboxConnectSessionResponse": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MailboxConnectSession"
          }
        },
        "required": [
          "data"
        ]
      },
      "OpenApiDocument": {
        "type": "object",
        "description": "The live OpenAPI document returned by `/openapi.json`.",
        "additionalProperties": true
      },
      "LimitsGuide": {
        "type": "object",
        "properties": {
          "default_page_size": {
            "type": "integer",
            "example": 20
          },
          "max_page_size": {
            "type": "integer",
            "example": 100
          },
          "bulk_sync_limit": {
            "type": "integer",
            "example": 100
          },
          "bulk_async_limit": {
            "type": "integer",
            "example": 1000
          },
          "max_async_jobs_per_account": {
            "type": "integer",
            "example": 3,
            "description": "Max concurrent running jobs per account (worker claim slots)."
          },
          "max_queued_async_jobs_per_account": {
            "type": "integer",
            "example": 25,
            "description": "Max jobs allowed in queued status while waiting for a running slot."
          },
          "staged_import_append_limit": {
            "type": "integer",
            "example": 500
          },
          "supported_scope_kinds": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "selection",
                "explorer_view",
                "saved_list",
                "saved_list_filtered",
                "campaign",
                "staged_upload"
              ]
            }
          },
          "supported_job_operations": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "api_lead_import",
                "add_to_campaign",
                "remove_from_campaign",
                "remove_from_all_campaigns",
                "pause_enrollments",
                "resume_enrollments",
                "add_to_lead_list",
                "remove_from_lead_list",
                "export_leads",
                "csv_lead_import_staged"
              ]
            }
          },
          "file_ingress": {
            "type": "object",
            "properties": {
              "staged_json_batches": {
                "type": "boolean"
              },
              "presigned_object_upload": {
                "type": "boolean"
              },
              "local_path_not_supported": {
                "type": "boolean"
              }
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Meta"
        ],
        "summary": "Health check",
        "description": "Checks that the API runtime is alive and can reach the backing database.",
        "security": [],
        "responses": {
          "200": {
            "description": "API and database are healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "ok",
                  "db": "ok"
                }
              }
            }
          },
          "503": {
            "description": "API is reachable but the database health check failed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "error",
                  "db": "error"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "getOpenApiDocument",
        "tags": [
          "Meta"
        ],
        "summary": "OpenAPI document",
        "description": "Returns the live OpenAPI contract served by Furnace.",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpenApiDocument"
                }
              }
            }
          }
        }
      }
    },
    "/v1/meta/limits": {
      "get": {
        "operationId": "getLimits",
        "tags": [
          "Meta"
        ],
        "summary": "API limits and bulk capabilities",
        "description": "Returns page sizes, sync/async bulk caps, queued vs running job quotas, supported scopes/operations, and file-ingress capabilities. Agents should configure chunking from this document rather than hard-coding limits.",
        "responses": {
          "200": {
            "description": "Limits and capabilities.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LimitsGuideResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/bulk/preview": {
      "post": {
        "operationId": "previewBulkOperation",
        "tags": [
          "Jobs"
        ],
        "summary": "Preview a bulk operation",
        "description": "Estimates matched/excluded/actionable counts for a scoped bulk mutation. Pass the returned `preview_id` when creating the job to bind execution to the preview.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkPreviewRequest"
              },
              "example": {
                "operation": "add_to_campaign",
                "campaign_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                "scope": {
                  "kind": "saved_list",
                  "list_id": "7c0d0f5a-2f61-4a2a-9f1d-1b2c3d4e5f60"
                },
                "exclusions": {
                  "list_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk preview.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkPreviewResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/imports/staged": {
      "post": {
        "operationId": "createStagedLeadImport",
        "tags": [
          "Leads"
        ],
        "summary": "Create staged lead import",
        "description": "Creates an uploading import job. Append lead batches with `appendStagedLeadImportRows`, then finalize with `finalizeStagedLeadImport`. Prefer this over inline async import for multi-thousand-lead files. Local filesystem paths are not accepted.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "201": {
            "description": "Staged import job created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StagedImportCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/jobs/{id}/staging-rows": {
      "post": {
        "operationId": "appendStagedLeadImportRows",
        "tags": [
          "Leads"
        ],
        "summary": "Append staged import rows",
        "description": "Appends up to 500 lead objects to a staged import job in `uploading` status.",
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StagedImportAppendRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rows appended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StagedImportAppendResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/jobs/{id}/finalize": {
      "post": {
        "operationId": "finalizeStagedLeadImport",
        "tags": [
          "Leads"
        ],
        "summary": "Finalize staged lead import",
        "description": "Marks a staged import job queued and enqueues worker processing. Idempotent if already queued/running/completed.",
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          }
        ],
        "responses": {
          "202": {
            "description": "Staged import finalized.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/uploads/presign": {
      "post": {
        "operationId": "createBulkUploadUrl",
        "tags": [
          "Leads"
        ],
        "summary": "Create presigned bulk upload URL",
        "description": "Optional file ingress for MCP hosts that can PUT directly to S3. Returns `upload_id` + temporary `upload_url`. Generic MCP clients that cannot perform arbitrary HTTP uploads should use staged JSON append instead. Local paths are never accepted by the server.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkUploadCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Presigned upload created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkUploadCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/people/export": {
      "post": {
        "operationId": "exportPeople",
        "tags": [
          "People"
        ],
        "summary": "Export people (async)",
        "description": "Starts one logical export job for a server-side scope. Use `projection: compact` for email/global_lead_id dumps. Poll `GET /v1/jobs/{id}` for `result.download_url`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportJobCreate"
              },
              "example": {
                "operation": "export_leads",
                "scope": {
                  "kind": "saved_list",
                  "list_id": "7c0d0f5a-2f61-4a2a-9f1d-1b2c3d4e5f60"
                },
                "projection": "compact"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Export job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/enroll": {
      "post": {
        "operationId": "enrollPeople",
        "tags": [
          "Leads"
        ],
        "summary": "Enroll people into campaign (async)",
        "description": "Starts one logical enroll job from a server-side scope (saved list, campaign, selection) with optional exclusions. Prefer this over sync add for large sets.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportJobCreate"
              },
              "example": {
                "operation": "add_to_campaign",
                "scope": {
                  "kind": "saved_list",
                  "list_id": "7c0d0f5a-2f61-4a2a-9f1d-1b2c3d4e5f60"
                },
                "exclusions": {
                  "list_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Enroll job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/lead-lists/{id}/members:bulk": {
      "post": {
        "operationId": "updateLeadListMembership",
        "tags": [
          "Lead Lists"
        ],
        "summary": "Bulk update lead list membership (async)",
        "description": "Starts one logical add/remove membership job. Body.operation must be `add_to_lead_list` or `remove_from_lead_list`. Source may be scope (list/campaign/selection) with optional exclusions on add.",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportJobCreate"
              },
              "example": {
                "operation": "add_to_lead_list",
                "scope": {
                  "kind": "campaign",
                  "campaign_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Membership job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns": {
      "get": {
        "operationId": "listCampaigns",
        "tags": [
          "Campaigns"
        ],
        "summary": "List campaigns",
        "description": "Lists campaigns in the authenticated account. Results are paginated and can optionally include soft-deleted campaigns.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/CampaignStatus"
          },
          {
            "$ref": "#/components/parameters/CampaignTagIds"
          },
          {
            "$ref": "#/components/parameters/IncludeDeletedCampaigns"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                      "name": "Q2 Pipeline",
                      "status": "running",
                      "source": "manual",
                      "created_at": "2026-05-21T18:00:00.000Z"
                    }
                  ],
                  "limit": 20,
                  "offset": 0,
                  "total_count": 1
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Create draft campaign",
        "description": "Creates a draft native campaign. Optional `flow` is normalized and validated on write. Supports idempotent retries with `Idempotency-Key`. See [CampaignFlow](/docs/reference/schemas/CampaignFlow/) and [Campaign setup](/docs/guides/campaign-setup/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignCreate"
              },
              "example": {
                "name": "Q2 Pipeline",
                "sending_interval_seconds": 1440,
                "mailbox_ids": [
                  "c23da7b6-df4e-4d2f-b100-4bb07b7d38d7"
                ],
                "flow": {
                  "nodes": [
                    {
                      "id": "leadSource-1",
                      "type": "leadSource",
                      "position": {
                        "x": 0,
                        "y": 0
                      },
                      "data": {
                        "label": "Lead Bucket",
                        "customFieldKeys": [
                          "company"
                        ]
                      }
                    }
                  ],
                  "edges": []
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Draft campaign created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignCreateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}": {
      "get": {
        "operationId": "getCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Get campaign",
        "description": "Returns one campaign within the API key account scope.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign response.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Update campaign",
        "description": "Updates mutable campaign fields. Mailboxes can be replaced wholesale with `mailbox_ids`, or incrementally edited with `add_mailbox_ids` and `remove_mailbox_ids`. Tags can be replaced with `tag_ids`, or incrementally edited with `add_tag_ids` and `remove_tag_ids`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignUpdate"
              },
              "example": {
                "name": "Q2 Pipeline Refresh",
                "sending_interval_seconds": 1800,
                "add_mailbox_ids": [
                  "c23da7b6-df4e-4d2f-b100-4bb07b7d38d7"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Delete campaign",
        "description": "Soft-deletes the campaign, stops enrollments, and tombstones campaign nodes. Smartlead campaigns remain read-only.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                },
                "example": {
                  "data": {
                    "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "deleted": true
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaign-tags": {
      "get": {
        "operationId": "listCampaignTags",
        "tags": [
          "Campaigns"
        ],
        "summary": "List campaign tags",
        "description": "Lists account-scoped campaign tag definitions.",
        "responses": {
          "200": {
            "description": "Campaign tag list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignTagListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createCampaignTag",
        "tags": [
          "Campaigns"
        ],
        "summary": "Create campaign tag",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignTagCreate"
              },
              "example": {
                "name": "Enterprise",
                "color": "#818CF8"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created campaign tag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignTagResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaign-tags/{id}": {
      "patch": {
        "operationId": "updateCampaignTag",
        "tags": [
          "Campaigns"
        ],
        "summary": "Update campaign tag",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignTagId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignTagUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated campaign tag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignTagResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteCampaignTag",
        "tags": [
          "Campaigns"
        ],
        "summary": "Delete campaign tag",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignTagId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign tag deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailbox-tags": {
      "get": {
        "operationId": "listMailboxTags",
        "tags": [
          "Mailboxes"
        ],
        "summary": "List mailbox tags",
        "description": "Lists account-scoped mailbox tag definitions.",
        "responses": {
          "200": {
            "description": "Mailbox tag list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxTagListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createMailboxTag",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Create mailbox tag",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MailboxTagCreate"
              },
              "example": {
                "name": "Warm-up pool",
                "color": "#22C55E"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created mailbox tag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxTagResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailbox-tags/{id}": {
      "patch": {
        "operationId": "updateMailboxTag",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Update mailbox tag",
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxTagId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MailboxTagUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated mailbox tag.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxTagResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteMailboxTag",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Delete mailbox tag",
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxTagId"
          }
        ],
        "responses": {
          "200": {
            "description": "Mailbox tag deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/status": {
      "patch": {
        "operationId": "updateCampaignStatus",
        "tags": [
          "Campaigns"
        ],
        "summary": "Update live campaign status",
        "description": "Changes status for a live campaign (`running`, `paused`, or `stopped`). Draft campaigns must use `POST /launch` instead. Emits campaign status webhooks.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CampaignStatusUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campaign status updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignStatusResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/flow-templates": {
      "get": {
        "operationId": "listFlowTemplates",
        "tags": [
          "Flow"
        ],
        "summary": "List flow templates",
        "description": "Returns starter flow graphs for common campaign patterns.",
        "responses": {
          "200": {
            "description": "Flow templates.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowTemplatesResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/pause": {
      "post": {
        "operationId": "pauseCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Pause campaign (deprecated)",
        "deprecated": true,
        "description": "Deprecated alias for `PATCH /v1/campaigns/{id}/status` with `{ \"status\": \"paused\" }`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign paused.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignStatusResponse"
                },
                "example": {
                  "data": {
                    "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "status": "paused"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/stop": {
      "post": {
        "operationId": "stopCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Stop campaign (deprecated)",
        "deprecated": true,
        "description": "Deprecated alias for `PATCH /v1/campaigns/{id}/status` with `{ \"status\": \"stopped\" }`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign stopped.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignStatusResponse"
                },
                "example": {
                  "data": {
                    "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "status": "stopped"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/resume": {
      "post": {
        "operationId": "resumeCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Resume campaign (deprecated)",
        "deprecated": true,
        "description": "Deprecated alias for `PATCH /v1/campaigns/{id}/status` with `{ \"status\": \"running\" }`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign resumed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignStatusResponse"
                },
                "example": {
                  "data": {
                    "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "status": "running"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/launch": {
      "post": {
        "operationId": "launchCampaign",
        "tags": [
          "Campaigns"
        ],
        "summary": "Launch draft campaign",
        "description": "Launches a draft campaign after verifying that it has a name, flow, and at least one mailbox. Furnace backfills enrollments, then sets status to `running` or `scheduled` depending on `lifecycle_schedule.start_on`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Campaign launched.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LaunchResponseEnvelope"
                },
                "example": {
                  "data": {
                    "id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "status": "running"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/enrollments/pause": {
      "post": {
        "operationId": "pauseCampaignEnrollments",
        "tags": [
          "Campaigns"
        ],
        "summary": "Pause enrollments",
        "description": "Manually pauses enrollments for the given global lead IDs in a native campaign and emits one `enrollment.pause_completed` batch webhook.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PauseEnrollmentsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enrollments paused.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentActionResponse"
                },
                "example": {
                  "data": {
                    "paused": 2,
                    "skipped": 0,
                    "errors": []
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/enrollments/resume": {
      "post": {
        "operationId": "resumeCampaignEnrollments",
        "tags": [
          "Campaigns"
        ],
        "summary": "Resume enrollments",
        "description": "Resumes manually paused enrollments for the given global lead IDs. Requires campaign status `running`. Emits one `enrollment.resume_completed` batch webhook.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResumeEnrollmentsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Enrollments resumed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentActionResponse"
                },
                "example": {
                  "data": {
                    "resumed": 2,
                    "skipped": 0,
                    "errors": []
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/flow": {
      "get": {
        "operationId": "getCampaignFlow",
        "tags": [
          "Flow"
        ],
        "summary": "Get campaign flow",
        "description": "Returns the normalized campaign flow graph. If a campaign has no saved flow, Furnace returns an empty `{ nodes: [], edges: [] }` payload. See [CampaignFlow](/docs/reference/schemas/CampaignFlow/) and [Campaign setup](/docs/guides/campaign-setup/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign flow.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignFlowResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateCampaignFlow",
        "tags": [
          "Flow"
        ],
        "summary": "Update campaign flow (deprecated alias)",
        "deprecated": true,
        "description": "Deprecated alias of `POST /v1/campaigns/{id}/flow`. Prefer POST with optional `If-Match`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FlowUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated normalized flow.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowSaveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "saveCampaignFlow",
        "tags": [
          "Flow"
        ],
        "summary": "Save campaign flow",
        "description": "Writes the canonical flow payload. Returns `flow`, `flow_revision`, and `field_sync`. Use `?dry_run=true` to validate without persisting. Optional `If-Match` header for optimistic concurrency. Request body: [FlowUpdate](/docs/reference/schemas/FlowUpdate/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "name": "dry_run",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean"
            },
            "description": "When true, validate without persisting."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FlowUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved normalized flow.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowSaveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "412": {
            "description": "Stale If-Match revision.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowRevisionConflictError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/flow/nodes/{nodeId}": {
      "patch": {
        "operationId": "patchCampaignFlowNode",
        "tags": [
          "Flow"
        ],
        "summary": "Patch flow node content",
        "description": "Live content-only patch for supported node types (email, waitTime, dataSender).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/FlowNodeId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FlowNodePatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated node content.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowSaveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/flow:validate": {
      "post": {
        "operationId": "validateCampaignFlow",
        "tags": [
          "Flow"
        ],
        "summary": "Validate campaign flow",
        "description": "Dry-runs flow normalization, validation, and lifecycle gating without writing changes. See [FlowValidateResult](/docs/reference/schemas/FlowValidateResult/) and [Campaign setup](/docs/guides/campaign-setup/).",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FlowUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Flow validation result.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowValidateResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/lead-fields": {
      "get": {
        "operationId": "getCampaignLeadFields",
        "tags": [
          "Lead fields"
        ],
        "summary": "Get lead fields",
        "description": "Returns the mapped standard lead fields and required custom lead field keys extracted from lead source nodes in the campaign flow.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead field definitions.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadFieldsResponse"
                },
                "example": {
                  "data": {
                    "standard": [
                      "email",
                      "first_name",
                      "last_name"
                    ],
                    "custom": [
                      "company",
                      "source"
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "appendCampaignLeadField",
        "tags": [
          "Lead fields"
        ],
        "summary": "Append lead field",
        "description": "Appends a custom lead field key to the campaign flow and preserves existing keys.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadFieldCreate"
              },
              "example": {
                "key": "source"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead field appended.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadFieldResponse"
                },
                "example": {
                  "data": {
                    "key": "source"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads": {
      "get": {
        "operationId": "listCampaignLeads",
        "tags": [
          "Leads"
        ],
        "summary": "List campaign leads",
        "description": "Lists non-deleted leads for a campaign. Search matches email and name fields.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createOrUpsertLead",
        "tags": [
          "Leads"
        ],
        "summary": "Create or upsert lead",
        "description": "Creates a lead or updates the existing non-deleted lead with the same campaign/email pair. This endpoint supports idempotent retries via `Idempotency-Key` and emits `lead.created` or `lead.updated` outbound webhook events.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadCreate"
              },
              "example": {
                "email": "jane@example.com",
                "name": "Jane Doe",
                "first_name": "Jane",
                "last_name": "Doe",
                "company_name": "Acme Co",
                "website": "https://www.acmeco.com",
                "linkedin_url": "https://www.linkedin.com/in/janedoe",
                "company_linkedin_url": "https://www.linkedin.com/company/acme-co",
                "custom_lead_data": {
                  "company": "Acme Co",
                  "source": "Landing Page"
                },
                "tags": [
                  "Hunter",
                  "ICP Fit"
                ],
                "email_verification": {
                  "status": "ok",
                  "provider": "millionverifier",
                  "quality": "good"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead updated or idempotent replay.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadUpsertResult"
                }
              }
            }
          },
          "201": {
            "description": "Lead created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadUpsertResult"
                },
                "example": {
                  "data": {
                    "id": "9c3cb55a-5e5e-47b6-a95e-31461779ce92",
                    "campaign_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "email": "jane@example.com",
                    "first_name": "Jane",
                    "custom_lead_data": {
                      "company": "Acme Co",
                      "source": "Landing Page"
                    },
                    "source": "api",
                    "created_at": "2026-05-21T18:00:00.000Z"
                  },
                  "created": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads/{leadId}": {
      "get": {
        "operationId": "getLead",
        "tags": [
          "Leads"
        ],
        "summary": "Get lead",
        "description": "Returns one active lead in the campaign.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/LeadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead response.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateLead",
        "tags": [
          "Leads"
        ],
        "summary": "Update lead",
        "description": "Updates mutable lead fields and emits `lead.updated`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/LeadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadUpdate"
              },
              "example": {
                "first_name": "Jane",
                "company_name": "Acme Incorporated",
                "custom_lead_data": {
                  "company": "Acme Incorporated",
                  "source": "Manual import"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated lead.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteLead",
        "tags": [
          "Leads"
        ],
        "summary": "Delete lead",
        "description": "Soft-deletes the lead, stops its enrollments, cancels queued campaign message jobs, and emits `lead.deleted`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/LeadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                },
                "example": {
                  "data": {
                    "id": "9c3cb55a-5e5e-47b6-a95e-31461779ce92",
                    "deleted": true
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads/bulk": {
      "post": {
        "operationId": "bulkSyncLeads",
        "tags": [
          "Leads"
        ],
        "summary": "Bulk sync leads",
        "description": "Synchronously imports or upserts up to 100 leads in a single request. Per-row lead webhooks are suppressed; Furnace emits one `lead.bulk_import.completed` batch event. Supports idempotent retries with `Idempotency-Key`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkLeadsRequest"
              },
              "example": {
                "leads": [
                  {
                    "email": "jane@example.com",
                    "first_name": "Jane",
                    "custom_lead_data": {
                      "company": "Acme Co",
                      "source": "Landing Page"
                    },
                    "tags": [
                      "Hunter",
                      "ICP Fit"
                    ],
                    "email_verification": {
                      "status": "ok",
                      "provider": "millionverifier"
                    }
                  },
                  {
                    "email": "max@example.com",
                    "first_name": "Max",
                    "custom_lead_data": {
                      "company": "Northwind",
                      "source": "Conference"
                    },
                    "tags": [
                      "Apollo"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk import results.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkLeadsResult"
                },
                "example": {
                  "imported": 2,
                  "incomplete": 0,
                  "failed": 0,
                  "errors": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads/bulk/async": {
      "post": {
        "operationId": "queueAsyncLeadImport",
        "tags": [
          "Jobs"
        ],
        "summary": "Queue async lead import",
        "description": "Queues an async import job for up to 1000 leads. Furnace allows at most 3 queued or running async jobs per account at a time. Per-row `lead.created` / `lead.updated` webhooks are suppressed during processing; a single `lead.bulk_import.completed` event is emitted when the job completes successfully.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AsyncBulkLeadsRequest"
              },
              "example": {
                "leads": [
                  {
                    "email": "jane@example.com",
                    "first_name": "Jane",
                    "custom_lead_data": {
                      "company": "Acme Co",
                      "source": "Landing Page"
                    },
                    "tags": [
                      "Hunter"
                    ],
                    "email_verification": {
                      "status": "ok",
                      "provider": "millionverifier"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Async import job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                },
                "example": {
                  "data": {
                    "id": "6a8584eb-0ee5-4d7d-8eb6-db9259914e18",
                    "campaign_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                    "account_id": "04bc2b35-a282-4581-a53f-50435d8309f1",
                    "created_by_api_key_id": "a66d06b0-dfe0-420b-8c05-1e7301ad1514",
                    "status": "queued",
                    "input": {
                      "leads": [
                        {
                          "email": "jane@example.com"
                        }
                      ]
                    },
                    "result": {},
                    "errors": []
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/jobs": {
      "post": {
        "operationId": "createAsyncJob",
        "tags": [
          "Jobs"
        ],
        "summary": "Create async bulk job",
        "description": "Creates one logical async job for a supported bulk operation. Prefer server-side `scope` (+ optional `exclusions`) over inline ID batches. Running concurrency is capped at 3 jobs per account; additional jobs remain queued. Poll `GET /v1/jobs/{id}`; cancel with `POST /v1/jobs/{id}/cancel`. One operation-specific `*.completed` webhook is emitted when the job finishes successfully.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportJobCreate"
              },
              "example": {
                "operation": "add_to_campaign",
                "campaign_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb",
                "scope": {
                  "kind": "saved_list",
                  "list_id": "7c0d0f5a-2f61-4a2a-9f1d-1b2c3d4e5f60"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Async job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads:add": {
      "post": {
        "operationId": "syncAddLeadsToCampaign",
        "tags": [
          "Leads"
        ],
        "summary": "Sync add leads to campaign",
        "description": "Adds up to 100 existing account people to a campaign by `global_lead_id`. Emits one `lead.added_to_campaign.completed` batch webhook.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GlobalLeadIdsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Leads added to campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipAddResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/leads:remove": {
      "post": {
        "operationId": "syncRemoveLeadsFromCampaign",
        "tags": [
          "Leads"
        ],
        "summary": "Sync remove leads from campaign",
        "description": "Removes up to 100 leads from a campaign by `global_lead_id`. Emits one `lead.removed_from_campaign.completed` batch webhook.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GlobalLeadIdsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Leads removed from campaign.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipRemoveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/leads:remove-from-all-campaigns": {
      "post": {
        "operationId": "syncRemoveLeadsFromAllCampaigns",
        "tags": [
          "Leads"
        ],
        "summary": "Sync remove leads from all campaigns",
        "description": "Removes up to 100 people from every campaign in the account. Emits one `lead.removed_from_all_campaigns.completed` batch webhook.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GlobalLeadIdsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Leads removed from all campaigns.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MembershipRemoveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/people": {
      "get": {
        "operationId": "listPeople",
        "tags": [
          "People"
        ],
        "summary": "List account people",
        "description": "Returns the account people explorer page with filters, sort, and pagination.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/PeopleSearch"
          },
          {
            "$ref": "#/components/parameters/PeopleSort"
          },
          {
            "$ref": "#/components/parameters/PeopleSortDirection"
          },
          {
            "$ref": "#/components/parameters/GlobalLeadIdsQuery"
          },
          {
            "$ref": "#/components/parameters/CampaignIdsQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Account people page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/people/{globalLeadId}": {
      "get": {
        "operationId": "getPerson",
        "tags": [
          "People"
        ],
        "summary": "Get person",
        "description": "Returns one account person and their campaign memberships.",
        "parameters": [
          {
            "$ref": "#/components/parameters/GlobalLeadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Person detail.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonDetailResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updatePerson",
        "tags": [
          "People"
        ],
        "summary": "Update person profile",
        "description": "Updates profile fields on all lead rows for the given global lead id.",
        "parameters": [
          {
            "$ref": "#/components/parameters/GlobalLeadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PersonUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated person.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/lead-lists": {
      "get": {
        "operationId": "listLeadLists",
        "tags": [
          "Lead lists"
        ],
        "summary": "List saved lead lists",
        "responses": {
          "200": {
            "description": "Saved lead lists.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadSavedListArrayResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createLeadList",
        "tags": [
          "Lead lists"
        ],
        "summary": "Create saved lead list",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadSavedListCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created lead list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadSavedListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/lead-lists/{id}": {
      "get": {
        "operationId": "getLeadList",
        "tags": [
          "Lead lists"
        ],
        "summary": "Get saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadSavedListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateLeadList",
        "tags": [
          "Lead lists"
        ],
        "summary": "Update saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadSavedListUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated lead list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadSavedListResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "deleteLeadList",
        "tags": [
          "Lead lists"
        ],
        "summary": "Delete saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "responses": {
          "200": {
            "description": "Lead list deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/lead-lists/{id}/people": {
      "get": {
        "operationId": "listLeadListPeople",
        "tags": [
          "Lead lists"
        ],
        "summary": "List people in saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          }
        ],
        "responses": {
          "200": {
            "description": "People in list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/lead-lists/{id}/members": {
      "post": {
        "operationId": "addLeadListMembers",
        "tags": [
          "Lead lists"
        ],
        "summary": "Add members to saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GlobalLeadIdsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Members added.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadListMembersResultResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "removeLeadListMembers",
        "tags": [
          "Lead lists"
        ],
        "summary": "Remove members from saved lead list",
        "parameters": [
          {
            "$ref": "#/components/parameters/LeadListId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GlobalLeadIdsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Members removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LeadListMembersResultResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/jobs/{id}": {
      "get": {
        "operationId": "getAsyncImportJob",
        "tags": [
          "Jobs"
        ],
        "summary": "Get async import job",
        "description": "Returns one async bulk job for the authenticated account.",
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Async import job.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/jobs/{id}/cancel": {
      "post": {
        "operationId": "cancelBulkJob",
        "tags": [
          "Jobs"
        ],
        "summary": "Cancel async bulk job",
        "description": "Requests cancellation. Queued/uploading jobs become cancelled immediately; running jobs stop between chunks.",
        "parameters": [
          {
            "$ref": "#/components/parameters/JobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancellation requested.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportJobResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailboxes": {
      "get": {
        "operationId": "listMailboxes",
        "tags": [
          "Mailboxes"
        ],
        "summary": "List mailboxes",
        "description": "Lists active account mailboxes. Furnace strips `smtp_password` and `imap_password` before returning each mailbox. Results can be filtered by mailbox tags.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/MailboxTagIds"
          }
        ],
        "responses": {
          "200": {
            "description": "Mailbox page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailboxes/{id}": {
      "patch": {
        "operationId": "updateMailbox",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Update mailbox",
        "description": "Updates mailbox tag assignments. Mailbox profile and credential fields remain read-only on the Client API.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MailboxUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated mailbox.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "get": {
        "operationId": "getMailbox",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Get mailbox",
        "description": "Returns one mailbox without secret password fields.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxId"
          }
        ],
        "responses": {
          "200": {
            "description": "Mailbox response.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads": {
      "get": {
        "operationId": "listThreads",
        "tags": [
          "Inbox"
        ],
        "summary": "List inbox threads",
        "description": "Lists inbox threads in the authenticated account. By default only threads with at least one inbound reply are returned. Newest/Oldest sort and `date_from`/`date_to` use `last_inbound_at` (latest lead reply). The `q` parameter searches subject, participants, lead identity/company, campaign name, thread tags, and message bodies.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Search"
          },
          {
            "$ref": "#/components/parameters/CampaignFilter"
          },
          {
            "$ref": "#/components/parameters/MailboxFilter"
          },
          {
            "$ref": "#/components/parameters/UnreadOnly"
          },
          {
            "$ref": "#/components/parameters/ConversationStatusFilter"
          },
          {
            "$ref": "#/components/parameters/ThreadCategoryFilter"
          },
          {
            "$ref": "#/components/parameters/ThreadTagIdsFilter"
          },
          {
            "$ref": "#/components/parameters/DateFrom"
          },
          {
            "$ref": "#/components/parameters/DateTo"
          },
          {
            "$ref": "#/components/parameters/HasReplyOnly"
          }
        ],
        "responses": {
          "200": {
            "description": "Thread page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}": {
      "get": {
        "operationId": "getThread",
        "tags": [
          "Inbox"
        ],
        "summary": "Get thread",
        "description": "Returns one inbox thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Thread response.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "patch": {
        "operationId": "updateThread",
        "tags": [
          "Inbox"
        ],
        "summary": "Update thread",
        "description": "Updates thread category, conversation status, and/or read state. Category changes emit a `reply.categorized` webhook when configured.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadUpdate"
              },
              "example": {
                "category": "Interested",
                "conversation_status": "closed",
                "read": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated thread.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/messages": {
      "get": {
        "operationId": "listThreadMessages",
        "tags": [
          "Inbox"
        ],
        "summary": "List thread messages",
        "description": "Lists messages in the thread ordered from oldest to newest.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Thread messages.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageListResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "306a0f4d-2aca-4d34-ab18-53a4b50b10eb",
                      "thread_id": "f064bce3-eb45-4edf-b7d0-6d316846f4f6",
                      "direction": "sent",
                      "subject": "Furnace API thread",
                      "body_text": "First touch",
                      "from_email": "sender@example.com",
                      "to_email": "lead@example.com",
                      "received_at": "2026-05-21T17:59:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/reply": {
      "post": {
        "operationId": "createReplyJob",
        "tags": [
          "Inbox"
        ],
        "summary": "Create reply job",
        "description": "Creates an outbound inbox reply job. When `in_reply_to_message_id` is omitted, Furnace targets the latest message in the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplyRequest"
              },
              "example": {
                "body_text": "Thanks for the reply."
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Reply job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplyJobResponse"
                },
                "example": {
                  "data": {
                    "id": "7e9f1f62-27f6-4474-b22c-7197e5480de4"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/forward": {
      "post": {
        "operationId": "createForwardJob",
        "tags": [
          "Inbox"
        ],
        "summary": "Create forward job",
        "description": "Creates an outbound inbox forward job for a specific message in the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForwardRequest"
              },
              "example": {
                "forward_message_id": "306a0f4d-2aca-4d34-ab18-53a4b50b10eb",
                "to_email": "referral@example.com",
                "body_text": "Sharing this thread."
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Forward job queued.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplyJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/out-of-office": {
      "put": {
        "operationId": "setThreadOutOfOffice",
        "tags": [
          "Inbox"
        ],
        "summary": "Set out of office",
        "description": "Marks a thread out of office and optionally schedules campaign resume.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OutOfOfficeUpdate"
              },
              "example": {
                "resume_mode": "scheduled",
                "resume_at": "2026-07-01T00:00:00.000Z"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Out-of-office updated.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutOfOfficeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "delete": {
        "operationId": "clearThreadOutOfOffice",
        "tags": [
          "Inbox"
        ],
        "summary": "Clear out of office",
        "description": "Clears out-of-office state for a thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "responses": {
          "200": {
            "description": "Out-of-office cleared.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/replace-lead/preview": {
      "get": {
        "operationId": "previewThreadLeadReplacement",
        "tags": [
          "Inbox"
        ],
        "summary": "Preview replace lead",
        "description": "Read-only preview of what `replaceThreadLead` would do for a candidate email on this thread. Call this before writing when you need to know whether the address will create a new contact or attach to an existing campaign lead, whether the address is on the block list, and whether the attach would be refused (same email as the current lead, or existing contact with no live enrollment). `mode`, `allowed`, and `disallowed_reason` use the same vocabulary as the write path errors.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          },
          {
            "name": "email",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "email"
            },
            "description": "Candidate replacement email to preview."
          }
        ],
        "responses": {
          "200": {
            "description": "Replacement preview.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplaceLeadPreviewResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/replace-lead": {
      "post": {
        "operationId": "replaceThreadLead",
        "tags": [
          "Inbox"
        ],
        "summary": "Replace lead",
        "description": "Replaces the thread lead with a new contact and optionally queues a forward job.\n\nTwo modes, reported in the response `mode` field:\n- `created` — the address is new to this campaign. A lead is inserted, the conversation moves to them, and the original lead is archived.\n- `attached` — the address is already a live lead in this campaign. That existing contact is reused (their profile and sequence stay as they are), the conversation moves to them, the original lead is retired as stopped/replaced, and any duplicate rows for the same address have their sequences stopped (`retired_sibling_count`). On attach, `new_lead_id` and `target_lead_id` are that pre-existing contact.\n\nAttach happens automatically when the address matches; there is no opt-in flag. The call fails with 409 `target_missing_enrollment` when the existing contact has no live enrollment (nothing to send against). Prefer calling `previewThreadLeadReplacement` first to inspect `mode`, `allowed`, block-list status, and `disallowed_reason` before writing.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceLeadRequest"
              },
              "example": {
                "new_email": "referral@example.com",
                "new_name": "Jane Doe"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Lead replaced.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplaceLeadResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "403": {
            "$ref": "#/components/responses/ForbiddenError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "409": {
            "$ref": "#/components/responses/ConflictError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/tags:add": {
      "post": {
        "operationId": "addThreadTag",
        "tags": [
          "Inbox"
        ],
        "summary": "Add thread tag",
        "description": "Assigns an existing account thread tag to the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadTagAssignmentRequest"
              },
              "example": {
                "tag_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag assigned.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadTagAssignmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/threads/{id}/tags:remove": {
      "post": {
        "operationId": "removeThreadTag",
        "tags": [
          "Inbox"
        ],
        "summary": "Remove thread tag",
        "description": "Removes a thread tag assignment from the thread.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ThreadId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ThreadTagAssignmentRequest"
              },
              "example": {
                "tag_id": "1d8dc901-3d2d-4d9f-9dcc-4f8b3aa1a1fb"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag removed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadTagAssignmentResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/thread-tags": {
      "get": {
        "operationId": "listThreadTags",
        "tags": [
          "Inbox"
        ],
        "summary": "List thread tags",
        "description": "Lists account thread tags available for assignment.",
        "responses": {
          "200": {
            "description": "Thread tags.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ThreadTagListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/message-jobs/{id}": {
      "get": {
        "operationId": "getMessageJob",
        "tags": [
          "Inbox"
        ],
        "summary": "Get message job",
        "description": "Returns the status of an outbound inbox reply or forward job.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MessageJobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Message job status.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageJobResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/message-jobs/{id}/cancel": {
      "post": {
        "operationId": "cancelMessageJob",
        "tags": [
          "Inbox"
        ],
        "summary": "Cancel message job",
        "description": "Cancels a queued or failed outbound inbox message job.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MessageJobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelled message job.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/message-jobs/{id}/send-now": {
      "post": {
        "operationId": "sendMessageJobNow",
        "tags": [
          "Inbox"
        ],
        "summary": "Send message job now",
        "description": "Requests immediate send for a queued outbound inbox message job.",
        "parameters": [
          {
            "$ref": "#/components/parameters/MessageJobId"
          }
        ],
        "responses": {
          "200": {
            "description": "Updated message job.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MessageJobResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/block-list": {
      "get": {
        "operationId": "listBlockListEntries",
        "tags": [
          "Block list"
        ],
        "summary": "List block list",
        "description": "Lists block-list entries in the authenticated account.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Offset"
          },
          {
            "$ref": "#/components/parameters/Search"
          }
        ],
        "responses": {
          "200": {
            "description": "Block-list page.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlockListListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createBlockListEntry",
        "tags": [
          "Block list"
        ],
        "summary": "Add block list entry",
        "description": "Creates a block-list entry for one email address or one domain host. `type: email` matches that address only. `type: domain` matches every address whose host equals `value` (`example.com` matches `pat@example.com`, not `pat@mail.example.com`). Send the host only — not `@example.com` and not a full email. If an identical `value` + `type` already exists, Furnace returns the existing row instead of creating a duplicate.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BlockListCreate"
              },
              "examples": {
                "email": {
                  "summary": "Block one address",
                  "value": {
                    "value": "blocked@example.com",
                    "type": "email",
                    "reason": "manual"
                  }
                },
                "domain": {
                  "summary": "Block every address at a host",
                  "value": {
                    "value": "example.com",
                    "type": "domain",
                    "reason": "manual"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Block-list entry already existed.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlockListResponse"
                }
              }
            }
          },
          "201": {
            "description": "Block-list entry created.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlockListResponse"
                },
                "example": {
                  "data": {
                    "id": "eb3a28d2-7328-4d02-9dad-4d1ee61d1952",
                    "account_id": "04bc2b35-a282-4581-a53f-50435d8309f1",
                    "value": "blocked@example.com",
                    "type": "email",
                    "reason": "manual"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/block-list/{id}": {
      "delete": {
        "operationId": "deleteBlockListEntry",
        "tags": [
          "Block list"
        ],
        "summary": "Delete block list entry",
        "description": "Deletes a block-list entry in the authenticated account.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BlockListId"
          }
        ],
        "responses": {
          "200": {
            "description": "Block-list entry deleted.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteResponse"
                },
                "example": {
                  "data": {
                    "id": "eb3a28d2-7328-4d02-9dad-4d1ee61d1952",
                    "deleted": true
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/campaigns/{id}/stats": {
      "get": {
        "operationId": "getCampaignStats",
        "tags": [
          "Stats"
        ],
        "summary": "Campaign stats",
        "description": "Returns daily and aggregate campaign stats. When `start_date` and `end_date` are omitted, Furnace defaults the range to campaign creation date through today.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CampaignId"
          },
          {
            "$ref": "#/components/parameters/StartDate"
          },
          {
            "$ref": "#/components/parameters/EndDate"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign stats.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignStatsResponse"
                },
                "example": {
                  "data": {
                    "daily": [
                      {
                        "date": "2026-05-20",
                        "sent": 15,
                        "replied": 3,
                        "positiveReply": 1,
                        "bounce": 0
                      }
                    ],
                    "totals": {
                      "sentCount": 15,
                      "repliedCount": 3,
                      "positiveReplyCount": 1,
                      "bounceCount": 0,
                      "lastBounceAt": null,
                      "enrollmentCount": 42,
                      "terminalEnrollmentCount": 9,
                      "contactedEnrollmentCount": 12
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "getWebhookSettings",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get webhook settings",
        "description": "Returns account-level webhook URL, signing secret, and enabled event types.",
        "responses": {
          "200": {
            "description": "Webhook settings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSettingsResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "put": {
        "operationId": "updateWebhookSettings",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update webhook settings",
        "description": "Updates account-level webhook URL, signing secret, and/or enabled events.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookSettingsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated webhook settings.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSettingsResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "tags": [
          "API keys"
        ],
        "summary": "List API keys",
        "description": "Lists account API keys. Secrets are never returned on list.",
        "responses": {
          "200": {
            "description": "API key list.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "tags": [
          "API keys"
        ],
        "summary": "Create API key",
        "description": "Creates an API key. The full secret is returned once in this response.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created API key with secret.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreatedResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/api-keys/{id}": {
      "delete": {
        "operationId": "revokeApiKey",
        "tags": [
          "API keys"
        ],
        "summary": "Revoke API key",
        "description": "Revokes an API key. Subsequent requests with that secret return 401.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiKeyId"
          }
        ],
        "responses": {
          "200": {
            "description": "Revoked API key.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailboxes/connect-sessions": {
      "post": {
        "operationId": "createMailboxConnectSession",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Start mailbox connect",
        "description": "Creates a mailbox connect session and returns a `connect_url` to complete mailbox provisioning in the Furnace app. Poll the session for status.",
        "responses": {
          "201": {
            "description": "Mailbox connect session.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxConnectSessionResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/mailboxes/connect-sessions/{id}": {
      "get": {
        "operationId": "getMailboxConnectSession",
        "tags": [
          "Mailboxes"
        ],
        "summary": "Get mailbox connect session",
        "description": "Returns mailbox connect session status (`pending`, `completed`, `expired`, or `failed`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/MailboxConnectSessionId"
          }
        ],
        "responses": {
          "200": {
            "description": "Mailbox connect session.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MailboxConnectSessionResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/UnauthorizedError"
          },
          "404": {
            "$ref": "#/components/responses/NotFoundError"
          },
          "429": {
            "$ref": "#/components/responses/RateLimitError"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    }
  }
}
