{
  "swagger": "2.0",
  "info": {
    "title": "Getread customer API",
    "version": "1",
    "description": "Customer operations. Responses may include additional fields."
  },
  "basePath": "/api/v1",
  "schemes": [
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/auth/me": {
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get profile",
        "description": "Get profile",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "user": {
                  "$ref": "#/definitions/UserProfile",
                  "description": "Your account profile."
                }
              },
              "required": [
                "user"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Profile"
        ],
        "summary": "Update profile",
        "description": "Update the authenticated user display name (1 to 200 Unicode characters). Email and authentication settings cannot be changed here.",
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Display name for this resource.",
                  "example": "Alex Morgan"
                }
              },
              "required": [
                "name"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "user": {
                  "$ref": "#/definitions/UserProfile",
                  "description": "Your account profile."
                }
              },
              "required": [
                "user"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        }
      }
    },
    "/campaigns": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "List campaigns in a workspace with cursor-based pagination.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Campaigns"
        ],
        "summary": "List campaigns",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "Copy next_cursor from the previous response. Omit this for the first page.",
            "name": "cursor",
            "in": "query",
            "x-example": "<next_cursor>"
          },
          {
            "type": "integer",
            "description": "Number of results to return per page. Defaults to 50.",
            "name": "limit",
            "in": "query",
            "x-example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "campaigns": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/Campaign"
                  },
                  "description": "Campaigns on this page.",
                  "example": [
                    {
                      "id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "workspace_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "name": "September newsletter",
                      "status": "draft",
                      "total_recipients": 0,
                      "created_at": "2026-09-27T12:00:00Z",
                      "updated_at": "2026-09-27T12:00:00Z"
                    }
                  ]
                },
                "next_cursor": {
                  "type": "string",
                  "description": "Pass this as cursor for the next page. Empty means this is the last page.",
                  "example": ""
                },
                "total": {
                  "type": "integer",
                  "description": "Total campaigns matching the filters.",
                  "example": 1
                }
              },
              "required": [
                "campaigns",
                "next_cursor",
                "total"
              ]
            }
          }
        },
        "x-required-scope": "campaigns:read"
      },
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Create a new email campaign draft.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Campaigns"
        ],
        "summary": "Create campaign",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "description": "Campaign details",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "preview_text": {
                  "type": "string",
                  "description": "Short text shown beside the subject in an inbox.",
                  "example": "A few things we made this month."
                },
                "reply_to": {
                  "type": "string",
                  "description": "Email address that receives replies.",
                  "example": "replies@example.com"
                },
                "json_design": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Editor design data used to reopen the email in the builder.",
                  "example": {}
                },
                "category_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Subscription category for this campaign.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                },
                "from_email": {
                  "type": "string",
                  "description": "Email address shown as the sender.",
                  "example": "hello@example.com"
                },
                "from_name": {
                  "type": "string",
                  "description": "Sender name shown beside the email address.",
                  "example": "Example Studio"
                },
                "html_body": {
                  "type": "string",
                  "description": "Optional text/html body. Supply HTML, plain text, or both. HTML-only sends include a generated text alternative.",
                  "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
                },
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "September newsletter"
                },
                "subject": {
                  "type": "string",
                  "description": "Subject line your recipients see.",
                  "example": "Your September update"
                },
                "template_id": {
                  "type": "string",
                  "description": "ID of the saved template to use.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                  "format": "uuid"
                },
                "text_body": {
                  "type": "string",
                  "description": "Optional authored text/plain alternative. Preserved literally. When blank or omitted with HTML, plain text is generated at delivery. Campaign text must include physical_address and unsubscribe_url or preference_url merge fields.",
                  "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
                }
              },
              "example": {
                "name": "September newsletter",
                "html_body": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>",
                "text_body": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}",
                "subject": "Your September update",
                "from_name": "Example Studio",
                "from_email": "hello@example.com"
              }
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/Campaign"
            }
          }
        },
        "x-required-scope": "campaigns:write"
      }
    },
    "/campaigns/{campaignID}": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Get campaign details by ID.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Campaigns"
        ],
        "summary": "Get campaign",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the campaign in this workspace.",
            "name": "campaignID",
            "in": "path",
            "required": true,
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Campaign"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "campaigns:read"
      },
      "put": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Replace a draft campaign's content and settings. This is not a partial update: include name and all content/settings to retain; omitted optional fields are cleared.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Campaigns"
        ],
        "summary": "Update campaign",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the campaign in this workspace.",
            "name": "campaignID",
            "in": "path",
            "required": true,
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          },
          {
            "description": "Complete content and settings to retain",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "preview_text": {
                  "type": "string",
                  "description": "Short text shown beside the subject in an inbox.",
                  "example": "A few things we made this month."
                },
                "reply_to": {
                  "type": "string",
                  "description": "Email address that receives replies.",
                  "example": "replies@example.com"
                },
                "json_design": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "Editor design data used to reopen the email in the builder.",
                  "example": {}
                },
                "category_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Subscription category for this campaign.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                },
                "from_email": {
                  "type": "string",
                  "description": "Email address shown as the sender.",
                  "example": "hello@example.com"
                },
                "from_name": {
                  "type": "string",
                  "description": "Sender name shown beside the email address.",
                  "example": "Example Studio"
                },
                "html_body": {
                  "type": "string",
                  "description": "Optional text/html body. Supply HTML, plain text, or both. HTML-only sends include a generated text alternative.",
                  "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
                },
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "September newsletter"
                },
                "subject": {
                  "type": "string",
                  "description": "Subject line your recipients see.",
                  "example": "Your September update"
                },
                "text_body": {
                  "type": "string",
                  "description": "Optional authored text/plain alternative. Preserved literally. When blank or omitted with HTML, plain text is generated at delivery. Campaign text must include physical_address and unsubscribe_url or preference_url merge fields.",
                  "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
                }
              },
              "example": {
                "name": "September newsletter",
                "html_body": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>",
                "text_body": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}",
                "subject": "Your September update",
                "from_name": "Example Studio",
                "from_email": "hello@example.com"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Campaign"
            }
          }
        },
        "x-required-scope": "campaigns:write"
      },
      "delete": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Delete a draft campaign. Cannot delete sent campaigns.",
        "tags": [
          "Campaigns"
        ],
        "summary": "Delete campaign",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the campaign in this workspace.",
            "name": "campaignID",
            "in": "path",
            "required": true,
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-required-scope": "campaigns:write"
      }
    },
    "/campaigns/{campaignID}/preview": {
      "get": {
        "tags": [
          "Campaigns"
        ],
        "summary": "Preview rendered content",
        "description": "Preview rendered content",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "campaignID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the campaign in this workspace.",
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          },
          {
            "name": "content_type",
            "in": "query",
            "type": "string",
            "enum": [
              "text/html",
              "text/plain"
            ],
            "description": "Format of the preview. Defaults to text/html.",
            "x-example": "text/html"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "string"
            },
            "examples": {
              "text/html": "<p>Hello!</p><p>123 Example Street, Chicago, IL 60601</p>"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "produces": [
          "text/html",
          "text/plain",
          "application/json"
        ],
        "x-required-scope": "campaigns:read"
      }
    },
    "/campaigns/{campaignID}/preflight": {
      "get": {
        "tags": [
          "Campaigns"
        ],
        "summary": "Review campaign before sending",
        "description": "Review campaign before sending",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "campaignID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the campaign in this workspace.",
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "campaign_revision": {
                  "type": "integer",
                  "description": "Current saved revision of the campaign.",
                  "example": 3
                },
                "review_token": {
                  "type": "string",
                  "description": "Token for this campaign review snapshot.",
                  "example": "<review-token>"
                },
                "list_ids": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "IDs of the lists selected for this campaign.",
                  "example": [
                    "7d264eba-7fe7-4b28-9d46-830beadcc423"
                  ]
                },
                "list_names": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Names of the selected lists.",
                  "example": [
                    "Newsletter subscribers"
                  ]
                },
                "campaign_updated_at": {
                  "type": "string",
                  "description": "When the reviewed campaign was last updated, in UTC.",
                  "example": "2026-09-27T12:00:00Z",
                  "format": "date-time"
                },
                "estimated_recipients": {
                  "type": "integer",
                  "description": "Distinct current members of the selected lists.",
                  "example": 100
                },
                "suppressed_recipients": {
                  "type": "integer",
                  "description": "Contacts excluded by suppression rules.",
                  "example": 5
                },
                "contact_ineligible_recipients": {
                  "type": "integer",
                  "description": "Contacts excluded because they have no recorded consent basis or are not active. Add a consent basis to contacts who agreed to marketing email to include them.",
                  "example": 3
                },
                "list_ineligible_recipients": {
                  "type": "integer",
                  "description": "Contacts excluded because they opted out of the selected lists.",
                  "example": 1
                },
                "category_ineligible_recipients": {
                  "type": "integer",
                  "description": "Contacts excluded because they unsubscribed from the campaign's email category.",
                  "example": 1
                },
                "deliverable_recipients": {
                  "type": "integer",
                  "description": "Contacts eligible to receive this campaign.",
                  "example": 90
                },
                "from_name": {
                  "type": "string",
                  "description": "Sender name shown beside the email address.",
                  "example": "Example Studio"
                },
                "from_email": {
                  "type": "string",
                  "description": "Email address shown as the sender.",
                  "example": "hello@example.com"
                },
                "workspace_name": {
                  "type": "string",
                  "description": "Name of the workspace sending the campaign.",
                  "example": "Example Studio"
                },
                "physical_address": {
                  "type": "string",
                  "description": "Postal address included in your emails.",
                  "example": "123 Example Street, Chicago, IL 60601"
                },
                "subject": {
                  "type": "string",
                  "description": "Subject line your recipients see.",
                  "example": "Your September update"
                },
                "blockers": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Issues to resolve before sending.",
                  "example": []
                },
                "warnings": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Things you may want to review before sending.",
                  "example": []
                }
              },
              "required": [
                "campaign_revision",
                "review_token",
                "list_ids",
                "list_names",
                "campaign_updated_at",
                "estimated_recipients",
                "suppressed_recipients",
                "contact_ineligible_recipients",
                "list_ineligible_recipients",
                "category_ineligible_recipients",
                "deliverable_recipients",
                "from_name",
                "from_email",
                "workspace_name",
                "physical_address",
                "subject",
                "blockers",
                "warnings"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "campaigns:read"
      }
    },
    "/campaigns/{campaignID}/stats": {
      "get": {
        "tags": [
          "Campaigns"
        ],
        "summary": "Get campaign stats",
        "description": "Get recipient delivery and engagement counts. opened/clicked count engaged recipients; total_opens/total_clicks count human events; machine_opens/machine_clicks count proxy and automated hits separately. Rates are fractions of sent recipients (0.25 means 25%).",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "campaignID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the campaign in this workspace.",
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign statistics",
            "schema": {
              "type": "object",
              "properties": {
                "campaign_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "ID of the campaign.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                },
                "total_recipients": {
                  "type": "integer",
                  "description": "Number of recipients in the campaign.",
                  "example": 100
                },
                "sent": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients whose messages were sent.",
                  "example": 100
                },
                "delivered": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients with a recorded delivery.",
                  "example": 98
                },
                "opened": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients with at least one recorded open.",
                  "example": 25
                },
                "clicked": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients with at least one recorded click.",
                  "example": 10
                },
                "bounced": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients whose messages bounced.",
                  "example": 2
                },
                "complained": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recipients who reported the message as spam.",
                  "example": 0
                },
                "total_opens": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recorded open events, including repeat opens.",
                  "example": 30
                },
                "total_clicks": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recorded click events, including repeat clicks.",
                  "example": 12
                },
                "machine_opens": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recorded open hits classified as machine activity (image proxies such as Apple Mail Privacy Protection, or automated clients), including repeats. Never included in opened or total_opens.",
                  "example": 40
                },
                "machine_clicks": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Recorded click hits classified as machine activity (automated clients or configured link-scanner ranges), including repeats. Never included in clicked or total_clicks.",
                  "example": 3
                },
                "open_rate": {
                  "type": "number",
                  "description": "Opened recipients divided by sent recipients. 0.25 means 25%.",
                  "example": 0.25
                },
                "click_rate": {
                  "type": "number",
                  "description": "Clicked recipients divided by sent recipients. 0.1 means 10%.",
                  "example": 0.1
                },
                "bounce_rate": {
                  "type": "number",
                  "description": "Bounced recipients divided by sent recipients. 0.02 means 2%.",
                  "example": 0.02
                }
              },
              "required": [
                "campaign_id",
                "total_recipients",
                "sent",
                "delivered",
                "opened",
                "clicked",
                "bounced",
                "complained",
                "total_opens",
                "total_clicks",
                "machine_opens",
                "machine_clicks",
                "open_rate",
                "click_rate",
                "bounce_rate"
              ]
            }
          },
          "404": {
            "description": "Campaign not found",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "campaigns:read"
      }
    },
    "/campaigns/{campaignID}/lists": {
      "get": {
        "tags": [
          "Campaigns"
        ],
        "summary": "Get campaign target lists",
        "description": "Get campaign target lists",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "campaignID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the campaign in this workspace.",
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "lists": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Unique ID for this resource.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "name": {
                        "type": "string",
                        "description": "Display name for this resource.",
                        "example": "September newsletter"
                      }
                    },
                    "required": [
                      "id",
                      "name"
                    ]
                  },
                  "description": "Lists selected as the campaign audience."
                }
              },
              "required": [
                "lists"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "campaigns:read"
      },
      "put": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Set the target lists for a campaign (replaces existing list assignments).",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Campaigns"
        ],
        "summary": "Set campaign lists",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the campaign in this workspace.",
            "name": "campaignID",
            "in": "path",
            "required": true,
            "x-example": "bb98bda7-cdca-425f-b341-8b9373cd2b53"
          },
          {
            "description": "List IDs",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "properties": {
                "list_ids": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "description": "Lists to use as the audience. Omit or send an empty array to clear the selection.",
                  "example": [
                    "7d264eba-7fe7-4b28-9d46-830beadcc423"
                  ]
                }
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "outcome": {
                  "type": "string",
                  "enum": [
                    "updated",
                    "unchanged"
                  ],
                  "description": "Result of applying the list selection.",
                  "example": "updated"
                },
                "changed": {
                  "type": "boolean",
                  "description": "Whether the list selection changed.",
                  "example": true
                },
                "campaign_revision": {
                  "type": "integer",
                  "format": "int64",
                  "description": "Current saved revision of the campaign.",
                  "example": 3
                }
              },
              "required": [
                "outcome",
                "changed",
                "campaign_revision"
              ]
            }
          },
          "409": {
            "description": "Campaign changed; review again",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          },
          "422": {
            "description": "Invalid or unavailable list selection",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid settings"
                }
              },
              "example": {
                "error": "Invalid settings"
              }
            }
          }
        },
        "x-required-scope": "campaigns:write"
      }
    },
    "/templates": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "List all email templates in a workspace.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Templates"
        ],
        "summary": "List templates",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Template"
              }
            }
          }
        },
        "x-required-scope": "templates:read"
      },
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Create a new email template.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Templates"
        ],
        "summary": "Create template",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "description": "Template data",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "category": {
                  "type": "string",
                  "description": "Template category.",
                  "example": "custom"
                },
                "description": {
                  "type": "string",
                  "description": "A short note to help you recognize this resource.",
                  "example": "Monthly product updates."
                },
                "html_body": {
                  "type": "string",
                  "description": "Optional text/html body. Supply HTML, plain text, or both. HTML-only sends include a generated text alternative.",
                  "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
                },
                "json_design": {
                  "type": "object",
                  "description": "Editor design data used to reopen the email in the builder.",
                  "example": {}
                },
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "September newsletter"
                },
                "text_body": {
                  "type": "string",
                  "description": "Optional authored text/plain alternative. Preserved literally. When blank or omitted with HTML, plain text is generated at delivery. Campaign text must include physical_address and unsubscribe_url or preference_url merge fields.",
                  "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
                }
              },
              "example": {
                "name": "September newsletter",
                "html_body": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>",
                "text_body": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
              }
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/Template"
            }
          }
        },
        "x-required-scope": "templates:write"
      }
    },
    "/templates/{templateID}": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Get an email template by ID.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Templates"
        ],
        "summary": "Get template",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the email template in this workspace.",
            "name": "templateID",
            "in": "path",
            "required": true,
            "x-example": "dbba51ab-c5e9-4883-a14c-a83c26b17daa"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Template"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "templates:read"
      },
      "put": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Replace an email template's content and metadata. This is not a partial update: include name and all content/metadata to retain; omitted optional fields are cleared.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Templates"
        ],
        "summary": "Update template",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the email template in this workspace.",
            "name": "templateID",
            "in": "path",
            "required": true,
            "x-example": "dbba51ab-c5e9-4883-a14c-a83c26b17daa"
          },
          {
            "description": "Complete content and metadata to retain",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "name"
              ],
              "properties": {
                "description": {
                  "type": "string",
                  "description": "A short note to help you recognize this resource.",
                  "example": "Monthly product updates."
                },
                "html_body": {
                  "type": "string",
                  "description": "Optional text/html body. Supply HTML, plain text, or both. HTML-only sends include a generated text alternative.",
                  "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
                },
                "json_design": {
                  "type": "object",
                  "description": "Editor design data used to reopen the email in the builder.",
                  "example": {}
                },
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "September newsletter"
                },
                "text_body": {
                  "type": "string",
                  "description": "Optional authored text/plain alternative. Preserved literally. When blank or omitted with HTML, plain text is generated at delivery. Campaign text must include physical_address and unsubscribe_url or preference_url merge fields.",
                  "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
                }
              },
              "example": {
                "name": "September newsletter",
                "html_body": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>",
                "text_body": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Template"
            }
          }
        },
        "x-required-scope": "templates:write"
      },
      "delete": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Delete an email template.",
        "tags": [
          "Templates"
        ],
        "summary": "Delete template",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the email template in this workspace.",
            "name": "templateID",
            "in": "path",
            "required": true,
            "x-example": "dbba51ab-c5e9-4883-a14c-a83c26b17daa"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-required-scope": "templates:write"
      }
    },
    "/templates/{templateID}/duplicate": {
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Create a copy of an existing template.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Templates"
        ],
        "summary": "Duplicate template",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the email template in this workspace.",
            "name": "templateID",
            "in": "path",
            "required": true,
            "x-example": "dbba51ab-c5e9-4883-a14c-a83c26b17daa"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/Template"
            }
          }
        },
        "x-required-scope": "templates:write"
      }
    },
    "/templates/{templateID}/preview": {
      "get": {
        "tags": [
          "Templates"
        ],
        "summary": "Preview rendered content",
        "description": "Preview rendered content",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "templateID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the email template in this workspace.",
            "x-example": "dbba51ab-c5e9-4883-a14c-a83c26b17daa"
          },
          {
            "name": "content_type",
            "in": "query",
            "type": "string",
            "enum": [
              "text/html",
              "text/plain"
            ],
            "description": "Format of the preview. Defaults to text/html.",
            "x-example": "text/html"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "string"
            },
            "examples": {
              "text/html": "<p>Hello!</p><p>123 Example Street, Chicago, IL 60601</p>"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "produces": [
          "text/html",
          "text/plain",
          "application/json"
        ],
        "x-required-scope": "templates:read"
      }
    },
    "/webhooks": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. List all outbound webhook endpoints for a workspace.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/Webhook"
              }
            }
          }
        },
        "x-required-scope": "webhooks:read"
      },
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. Create a new outbound webhook endpoint. The signing secret is returned only once.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Webhooks"
        ],
        "summary": "Create webhook endpoint",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "description": "Webhook configuration (maximum 16 KiB; unknown fields rejected)",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "url",
                "events"
              ],
              "properties": {
                "description": {
                  "type": "string",
                  "maxLength": 500,
                  "description": "A short note to help you recognize this resource.",
                  "example": "Monthly product updates."
                },
                "events": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 64,
                  "uniqueItems": true,
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "description": "Event names such as campaign.sent or contact.created.",
                  "example": [
                    "campaign.sent"
                  ]
                },
                "url": {
                  "type": "string",
                  "format": "uri",
                  "maxLength": 2048,
                  "description": "Public HTTPS endpoint; credentials, fragments, private addresses and unsafe ports are rejected.",
                  "example": "https://example.com/webhooks/getread"
                }
              }
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/WebhookWithSecret"
            }
          }
        },
        "x-required-scope": "webhooks:write"
      }
    },
    "/webhooks/{whid}": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. Get webhook endpoint details.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Webhooks"
        ],
        "summary": "Get webhook endpoint",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the webhook endpoint in this workspace.",
            "name": "whid",
            "in": "path",
            "required": true,
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Webhook"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "webhooks:read"
      },
      "put": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. Replace endpoint configuration, not a partial update. URL is required; omitted events become empty, description is cleared, and omitted status defaults to active. Requests are limited to 16 KiB and unknown fields are rejected.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Webhooks"
        ],
        "summary": "Update webhook endpoint",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the webhook endpoint in this workspace.",
            "name": "whid",
            "in": "path",
            "required": true,
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          },
          {
            "description": "Complete endpoint configuration",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "url"
              ],
              "properties": {
                "description": {
                  "type": "string",
                  "maxLength": 500,
                  "description": "A short note to help you recognize this resource.",
                  "example": "Monthly product updates."
                },
                "events": {
                  "type": "array",
                  "maxItems": 64,
                  "uniqueItems": true,
                  "items": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "description": "Event names such as campaign.sent or contact.created. Empty disables event subscriptions.",
                  "example": [
                    "campaign.sent"
                  ]
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "inactive"
                  ],
                  "default": "active",
                  "description": "Current state of this resource.",
                  "example": "active"
                },
                "url": {
                  "type": "string",
                  "format": "uri",
                  "maxLength": 2048,
                  "description": "Public HTTPS endpoint; credentials, fragments, private addresses and unsafe ports are rejected.",
                  "example": "https://example.com/webhooks/getread"
                }
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/Webhook"
            }
          }
        },
        "x-required-scope": "webhooks:write"
      },
      "delete": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. Delete a webhook endpoint. All pending deliveries will be cancelled.",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete webhook endpoint",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the webhook endpoint in this workspace.",
            "name": "whid",
            "in": "path",
            "required": true,
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-required-scope": "webhooks:write"
      }
    },
    "/webhooks/{whid}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook deliveries",
        "description": "Workspace owner or admin only. Supply next_cursor as cursor to fetch the next page.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "whid",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the webhook endpoint in this workspace.",
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          },
          {
            "name": "cursor",
            "in": "query",
            "type": "string",
            "description": "Copy next_cursor from the previous response. Omit this for the first page.",
            "x-example": "<next_cursor>"
          },
          {
            "name": "limit",
            "in": "query",
            "type": "integer",
            "default": 50,
            "maximum": 200,
            "description": "Number of results to return per page. Defaults to 50.",
            "x-example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "deliveries": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Unique ID for this resource.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "endpoint_id": {
                        "type": "string",
                        "description": "ID of the webhook endpoint.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "logical_event_id": {
                        "type": "string",
                        "x-nullable": true,
                        "description": "ID of the event that caused this delivery. May be null.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                      },
                      "event_type": {
                        "type": "string",
                        "description": "Name of the event sent to your endpoint.",
                        "example": "campaign.sent"
                      },
                      "status": {
                        "type": "string",
                        "description": "Current state of this resource.",
                        "example": "delivered"
                      },
                      "response_status": {
                        "type": "integer",
                        "x-nullable": true,
                        "description": "HTTP status returned by your endpoint. Null before a response.",
                        "example": 200
                      },
                      "attempt_count": {
                        "type": "integer",
                        "description": "Number of delivery attempts so far.",
                        "example": 1
                      },
                      "next_retry_at": {
                        "type": "string",
                        "format": "date-time",
                        "x-nullable": true,
                        "description": "Next retry time in UTC, or null if none is scheduled.",
                        "example": null
                      },
                      "delivered_at": {
                        "type": "string",
                        "format": "date-time",
                        "x-nullable": true,
                        "description": "Successful delivery time in UTC, or null if not delivered.",
                        "example": "2026-09-27T12:00:00Z"
                      },
                      "created_at": {
                        "type": "string",
                        "description": "When this resource was created, in UTC.",
                        "example": "2026-09-27T12:00:00Z",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "endpoint_id",
                      "logical_event_id",
                      "event_type",
                      "status",
                      "response_status",
                      "attempt_count",
                      "next_retry_at",
                      "delivered_at",
                      "created_at"
                    ]
                  },
                  "description": "Webhook delivery attempts on this page."
                },
                "next_cursor": {
                  "type": "string",
                  "description": "Pass this as cursor for the next page. Empty means this is the last page.",
                  "example": ""
                }
              },
              "required": [
                "deliveries",
                "next_cursor"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "webhooks:read"
      }
    },
    "/webhooks/{whid}/test": {
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Workspace owner or admin only. Send a test payload to a webhook endpoint to verify connectivity.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Webhooks"
        ],
        "summary": "Test webhook",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the webhook endpoint in this workspace.",
            "name": "whid",
            "in": "path",
            "required": true,
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string",
                  "description": "test queued",
                  "example": "test queued"
                }
              },
              "required": [
                "status"
              ]
            }
          }
        },
        "x-required-scope": "webhooks:write"
      }
    },
    "/webhooks/{whid}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate webhook signing secret",
        "description": "Workspace owner or admin only. Rotation may return 409 while pending deliveries use the previous secret. The new secret is returned once.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "whid",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the webhook endpoint in this workspace.",
            "x-example": "fc4cb725-4f17-411b-8d48-01b952323816"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "$ref": "#/definitions/WebhookWithSecret"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "webhooks:write"
      }
    },
    "/automations": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "List automations in a workspace.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Automations"
        ],
        "summary": "List automations",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "Copy next_cursor from the previous response. Omit this for the first page.",
            "name": "cursor",
            "in": "query",
            "x-example": "<next_cursor>"
          },
          {
            "type": "integer",
            "description": "Number of results to return per page. Defaults to 50.",
            "name": "limit",
            "in": "query",
            "x-example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "automations": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/Automation"
                  },
                  "description": "Automations on this page."
                },
                "next_cursor": {
                  "type": "string",
                  "description": "Pass this as cursor for the next page. Empty means this is the last page.",
                  "example": ""
                }
              },
              "required": [
                "automations",
                "next_cursor"
              ]
            }
          }
        },
        "x-required-scope": "automations:read"
      },
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Create a draft automation with a trigger. Add steps with PUT /automations/{automationID}/save, then activate it.",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "tags": [
          "Automations"
        ],
        "summary": "Create automation",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "description": "Automation definition",
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "required": [
                "name",
                "trigger_type"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "Welcome series"
                },
                "trigger_config": {
                  "type": "object",
                  "description": "For list_join supply list_id (UUID); tag_added requires tag; campaign_opened/campaign_clicked require campaign_id (UUID); manual uses {}. Configuration is validated on activation.",
                  "example": {}
                },
                "trigger_type": {
                  "type": "string",
                  "enum": [
                    "manual",
                    "list_join",
                    "tag_added",
                    "campaign_opened",
                    "campaign_clicked"
                  ],
                  "description": "Event that enrolls a contact in the automation.",
                  "example": "manual"
                }
              }
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "schema": {
              "$ref": "#/definitions/Automation"
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Get an automation with its steps.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Automations"
        ],
        "summary": "Get automation",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the automation in this workspace.",
            "name": "automationID",
            "in": "path",
            "required": true,
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "$ref": "#/definitions/AutomationWithSteps"
            }
          },
          "404": {
            "description": "Not Found",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "automations:read"
      },
      "delete": {
        "tags": [
          "Automations"
        ],
        "summary": "Delete automation",
        "description": "Delete a non-active automation. Pause an active automation before deleting it.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted"
          },
          "400": {
            "description": "Cannot delete an active automation",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "404": {
            "description": "Automation not found",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/save": {
      "put": {
        "tags": [
          "Automations"
        ],
        "summary": "Atomically save automation editor snapshot",
        "description": "Replace settings and steps atomically, not a partial update. Supply expected_status and expected_updated_at from the detail response's status and updated_at. pause_before_save must be true for active automations and false otherwise. Stale snapshots return 409; invalid settings return 422. Preserve stable step IDs and include every step to retain; omitted steps are archived. Activation requires a nonempty, acyclic graph reachable from the lowest sort_order step and valid trigger/step configurations.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          },
          {
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Display name for this resource.",
                  "example": "Welcome series"
                },
                "trigger_type": {
                  "type": "string",
                  "enum": [
                    "manual",
                    "list_join",
                    "tag_added",
                    "campaign_opened",
                    "campaign_clicked"
                  ],
                  "description": "Event that enrolls a contact in the automation.",
                  "example": "manual"
                },
                "trigger_config": {
                  "type": "object",
                  "description": "manual uses {}; list_join requires list_id; tag_added requires tag; campaign_opened/campaign_clicked require campaign_id.",
                  "properties": {
                    "list_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "List used by this trigger or step.",
                      "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                    },
                    "tag": {
                      "type": "string",
                      "description": "Tag used by this trigger or step.",
                      "example": "subscriber"
                    },
                    "campaign_id": {
                      "type": "string",
                      "format": "uuid",
                      "description": "ID of the campaign.",
                      "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                    }
                  },
                  "example": {}
                },
                "steps": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "step_type"
                    ],
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Stable UUID, including a client-generated UUID for a new step; use the same UUID in graph edges. Omit to generate an ID.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "step_type": {
                        "type": "string",
                        "enum": [
                          "send_email",
                          "wait",
                          "condition",
                          "add_tag",
                          "remove_tag",
                          "add_to_list",
                          "remove_from_list",
                          "end"
                        ],
                        "description": "Action this step performs.",
                        "example": "end"
                      },
                      "config": {
                        "type": "object",
                        "description": "Settings for this step, checked on activation. End steps use {}. Other step types need the fields described below.",
                        "properties": {
                          "subject": {
                            "type": "string",
                            "description": "Subject line. Required for send_email steps.",
                            "example": "Your September update"
                          },
                          "html_body": {
                            "type": "string",
                            "description": "Email HTML with an unsubscribe link. Required for send_email; include a postal address here or in physical_address.",
                            "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
                          },
                          "physical_address": {
                            "type": "string",
                            "description": "Postal address for send_email steps. Required if the HTML does not include one.",
                            "example": "123 Example Street, Chicago, IL 60601"
                          },
                          "duration": {
                            "type": "integer",
                            "minimum": 1,
                            "description": "Positive wait duration. Required for wait steps.",
                            "example": 1
                          },
                          "unit": {
                            "type": "string",
                            "enum": [
                              "seconds",
                              "minutes",
                              "hours",
                              "days"
                            ],
                            "default": "seconds",
                            "description": "Unit for the wait duration. Defaults to seconds.",
                            "example": "days"
                          },
                          "field": {
                            "type": "string",
                            "enum": [
                              "tags",
                              "status",
                              "open_count",
                              "click_count"
                            ],
                            "description": "Field for a condition step: tags, status, open_count, or click_count.",
                            "example": "tags"
                          },
                          "operator": {
                            "type": "string",
                            "enum": [
                              "contains",
                              "not_contains",
                              "equals",
                              "gt",
                              "lt",
                              "eq"
                            ],
                            "description": "Comparison for a condition: contains/not_contains for tags, equals for status, or gt/lt/eq for counts.",
                            "example": "contains"
                          },
                          "value": {
                            "description": "Condition value: a string for tags/status, or a nonnegative number or numeric string for counts.",
                            "example": "subscriber"
                          },
                          "campaign_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Campaign to check. Required for open_count and click_count conditions.",
                            "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                          },
                          "tag": {
                            "type": "string",
                            "description": "Tag to change. Required for add_tag and remove_tag steps.",
                            "example": "subscriber"
                          },
                          "list_id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "List to change. Required for add_to_list and remove_from_list steps.",
                            "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                          }
                        },
                        "example": {}
                      },
                      "next_step_id": {
                        "type": "string",
                        "description": "ID of the next step. Omit when this step ends the path.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "yes_step_id": {
                        "type": "string",
                        "description": "Next step when the condition matches.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "no_step_id": {
                        "type": "string",
                        "description": "Next step when the condition does not match.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "sort_order": {
                        "type": "integer",
                        "description": "Step position. The lowest position is the entry step.",
                        "example": 0
                      }
                    }
                  },
                  "description": "Steps in this automation."
                },
                "expected_status": {
                  "type": "string",
                  "enum": [
                    "draft",
                    "paused",
                    "active"
                  ],
                  "description": "Status from the latest automation detail response.",
                  "example": "draft"
                },
                "expected_updated_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "updated_at from the latest automation detail response.",
                  "example": "2026-09-27T12:00:00Z"
                },
                "pause_before_save": {
                  "type": "boolean",
                  "description": "Use true when editing an active automation; otherwise use false.",
                  "example": false
                }
              },
              "required": [
                "name",
                "trigger_type",
                "steps",
                "expected_status",
                "expected_updated_at"
              ],
              "example": {
                "name": "Welcome series",
                "trigger_type": "manual",
                "trigger_config": {},
                "steps": [
                  {
                    "step_type": "end",
                    "config": {},
                    "sort_order": 0
                  }
                ],
                "expected_status": "draft",
                "expected_updated_at": "2026-09-27T12:00:00Z",
                "pause_before_save": false
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "$ref": "#/definitions/AutomationWithSteps"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/activate": {
      "post": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Start an automation so it begins enrolling contacts on trigger.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Automations"
        ],
        "summary": "Activate automation",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the automation in this workspace.",
            "name": "automationID",
            "in": "path",
            "required": true,
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string",
                  "description": "Confirmation of the completed action.",
                  "example": "automation activated"
                }
              },
              "required": [
                "message"
              ]
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/pause": {
      "post": {
        "tags": [
          "Automations"
        ],
        "summary": "Pause automation",
        "description": "Pause new enrollments and defer processing of existing enrollments until resumed. Already admitted email deliveries are not recalled.",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "Paused",
            "schema": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string",
                  "description": "Confirmation of the completed action.",
                  "example": "automation paused"
                }
              },
              "required": [
                "message"
              ]
            }
          },
          "404": {
            "description": "Automation not found",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "example": {
                "error": "Not found"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/resume": {
      "post": {
        "tags": [
          "Automations"
        ],
        "summary": "Resume automation",
        "description": "Resume automation",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string",
                  "description": "Confirmation of the completed action.",
                  "example": "automation resumed"
                }
              },
              "required": [
                "message"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/archive": {
      "post": {
        "tags": [
          "Automations"
        ],
        "summary": "Archive automation",
        "description": "Archive automation",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string",
                  "description": "Confirmation of the completed action.",
                  "example": "automation archived"
                }
              },
              "required": [
                "message"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/duplicate": {
      "post": {
        "tags": [
          "Automations"
        ],
        "summary": "Duplicate automation",
        "description": "Duplicate automation",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "201": {
            "description": "Success",
            "schema": {
              "$ref": "#/definitions/AutomationWithSteps"
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/automations/{automationID}/analytics": {
      "get": {
        "tags": [
          "Automations"
        ],
        "summary": "Get step analytics",
        "description": "Get step analytics",
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "type": "string",
            "required": false,
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "automationID",
            "in": "path",
            "type": "string",
            "required": true,
            "description": "ID of the automation in this workspace.",
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "schema": {
              "type": "object",
              "properties": {
                "steps": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "step_id": {
                        "type": "string",
                        "description": "ID of the automation step.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "entered": {
                        "type": "integer",
                        "description": "Enrollments that entered this step.",
                        "example": 10
                      },
                      "completed": {
                        "type": "integer",
                        "description": "Enrollments that completed this step.",
                        "example": 8
                      },
                      "skipped": {
                        "type": "integer",
                        "description": "Enrollments that skipped this step.",
                        "example": 0
                      },
                      "failed": {
                        "type": "integer",
                        "description": "Enrollments that failed at this step.",
                        "example": 1
                      },
                      "exited": {
                        "type": "integer",
                        "description": "Enrollments that exited at this step.",
                        "example": 1
                      }
                    },
                    "required": [
                      "step_id",
                      "entered",
                      "completed",
                      "skipped",
                      "failed",
                      "exited"
                    ]
                  },
                  "description": "Enrollment counts for each step."
                }
              },
              "required": [
                "steps"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Authentication required",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Insufficient workspace role or membership",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "409": {
            "description": "Stale revision or conflicting state",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          }
        },
        "x-required-scope": "automations:read"
      }
    },
    "/automations/{automationID}/enrollments": {
      "get": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "List contacts enrolled in an automation.",
        "produces": [
          "application/json"
        ],
        "tags": [
          "Automations"
        ],
        "summary": "List enrollments",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the automation in this workspace.",
            "name": "automationID",
            "in": "path",
            "required": true,
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          },
          {
            "type": "string",
            "description": "Copy next_cursor from the previous response. Omit this for the first page.",
            "name": "cursor",
            "in": "query",
            "x-example": "<next_cursor>"
          },
          {
            "type": "integer",
            "description": "Number of results to return per page. Defaults to 50.",
            "name": "limit",
            "in": "query",
            "x-example": 25
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "schema": {
              "type": "object",
              "properties": {
                "enrollments": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "Unique ID for this resource.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "automation_id": {
                        "type": "string",
                        "description": "ID of the automation.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "contact_id": {
                        "type": "string",
                        "description": "ID of the enrolled contact.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "current_step_id": {
                        "type": "string",
                        "description": "Step the contact is currently on. Omitted when there is none.",
                        "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                        "format": "uuid"
                      },
                      "status": {
                        "type": "string",
                        "description": "Current state of this resource.",
                        "example": "active"
                      },
                      "enrolled_at": {
                        "type": "string",
                        "description": "When the contact entered the automation, in UTC.",
                        "example": "2026-09-27T12:00:00Z",
                        "format": "date-time"
                      },
                      "completed_at": {
                        "type": "string",
                        "description": "When the enrollment completed, in UTC. Omitted until complete.",
                        "example": "2026-09-27T12:00:00Z",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "id",
                      "automation_id",
                      "contact_id",
                      "status",
                      "enrolled_at"
                    ],
                    "example": {
                      "id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "automation_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "contact_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "current_step_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
                      "status": "active",
                      "enrolled_at": "2026-09-27T12:00:00Z"
                    }
                  },
                  "description": "Contact enrollments on this page."
                },
                "next_cursor": {
                  "type": "string",
                  "description": "Pass this as cursor for the next page. Empty means this is the last page.",
                  "example": ""
                }
              },
              "required": [
                "enrollments",
                "next_cursor"
              ]
            }
          }
        },
        "x-required-scope": "automations:read"
      }
    },
    "/automations/{automationID}/enrollments/{enrollmentID}": {
      "delete": {
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "description": "Cancel a contact's active enrollment in an automation.",
        "tags": [
          "Automations"
        ],
        "summary": "Cancel enrollment",
        "parameters": [
          {
            "type": "string",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "type": "string",
            "description": "ID of the automation in this workspace.",
            "name": "automationID",
            "in": "path",
            "required": true,
            "x-example": "bfbfdfe8-770d-44b8-9253-4aa6b63a0645"
          },
          {
            "type": "string",
            "description": "ID of the contact enrollment in this automation.",
            "name": "enrollmentID",
            "in": "path",
            "required": true,
            "x-example": "ccf748c3-de2a-4b9b-881b-c5f3d43fdf6e"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          }
        },
        "x-required-scope": "automations:write"
      }
    },
    "/transactional/send": {
      "post": {
        "tags": [
          "Application templates"
        ],
        "summary": "Send transactional email",
        "description": "Supply template_id and JSON attributes, or raw html/text bodies. Template requests render the subject and both saved parts; raw-body requests are literal. Rendered content is snapshotted at admission. Idempotency compares rendered content: template edits can make a retry return 409. Workspace scope comes from the source key, not X-Workspace-ID.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/ApplicationSendRequest"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "type": "string",
            "maxLength": 128,
            "description": "Your retry key for this workspace. Reusing it with the same rendered content returns the original send; different content returns 409.",
            "x-example": "order-A-1042"
          }
        ],
        "responses": {
          "201": {
            "description": "Accepted into the delivery queue; not a delivery confirmation",
            "schema": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Unique ID for this resource.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                },
                "workspace_id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Workspace this resource belongs to.",
                  "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
                },
                "to_email": {
                  "type": "string",
                  "description": "Recipient email address.",
                  "example": "alex@example.com"
                },
                "from_email": {
                  "type": "string",
                  "x-nullable": true,
                  "description": "Email address shown as the sender.",
                  "example": "hello@example.com"
                },
                "from_name": {
                  "type": "string",
                  "x-nullable": true,
                  "description": "Sender name shown beside the email address.",
                  "example": "Example Studio"
                },
                "subject": {
                  "type": "string",
                  "description": "Subject line your recipients see.",
                  "example": "Your order A-1042 is ready"
                },
                "status": {
                  "type": "string",
                  "description": "Current state of this resource.",
                  "example": "pending"
                },
                "tags": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  },
                  "x-nullable": true,
                  "description": "Metadata you can use to identify or filter the send.",
                  "example": {
                    "order_id": "A-1042"
                  }
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When this resource was created, in UTC.",
                  "example": "2026-09-27T12:00:00Z"
                },
                "idempotency_key": {
                  "type": "string",
                  "x-nullable": true,
                  "description": "Key for safely retrying the same send. Null when no key was supplied.",
                  "example": "order-A-1042"
                }
              },
              "required": [
                "id",
                "workspace_id",
                "to_email",
                "from_email",
                "from_name",
                "subject",
                "status",
                "tags",
                "created_at",
                "idempotency_key"
              ]
            }
          },
          "400": {
            "description": "Invalid request",
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Invalid request"
                }
              },
              "required": [
                "error"
              ],
              "example": {
                "error": "Invalid request"
              }
            }
          },
          "401": {
            "description": "Invalid source API key",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Unauthorized"
                }
              },
              "example": {
                "error": "Unauthorized"
              }
            }
          },
          "403": {
            "description": "Sending is not permitted",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Forbidden"
                }
              },
              "example": {
                "error": "Forbidden"
              }
            }
          },
          "404": {
            "description": "Template not found in this workspace",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Not found"
                }
              },
              "example": {
                "error": "Not found"
              }
            }
          },
          "409": {
            "description": "Idempotency key reused with different rendered content",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Conflict"
                }
              },
              "example": {
                "error": "Conflict"
              }
            }
          },
          "413": {
            "description": "Request body exceeds 576 KiB",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Request body too large"
                }
              },
              "example": {
                "error": "Request body too large"
              }
            }
          },
          "429": {
            "description": "Workspace sending rate exceeded. Respect Retry-After; limits may vary by workspace.",
            "headers": {
              "Retry-After": {
                "type": "integer",
                "description": "Seconds before retrying"
              }
            },
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Rate limit exceeded"
                }
              },
              "example": {
                "error": "Rate limit exceeded"
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable",
            "schema": {
              "type": "object",
              "required": [
                "error"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "description": "A short explanation of what went wrong.",
                  "example": "Service temporarily unavailable"
                }
              },
              "example": {
                "error": "Service temporarily unavailable"
              }
            }
          }
        },
        "x-required-scope": "transactional:send"
      }
    },
    "/transactional/preview": {
      "post": {
        "summary": "Preview a template with JSON attributes",
        "description": "Renders saved content without sending mail or consuming sending quota. Uses the same renderer as template sends.",
        "tags": [
          "Application templates"
        ],
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/TemplatePreviewRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rendered email",
            "schema": {
              "$ref": "#/definitions/TemplatePreviewResult"
            }
          },
          "400": {
            "description": "Invalid fields, JSON, variable syntax or values, or rendered size"
          },
          "401": {
            "description": "Invalid authentication"
          },
          "404": {
            "description": "Template not found in this workspace"
          },
          "413": {
            "description": "Request body exceeds 576 KiB"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "x-required-scope": "templates:read"
      }
    },
    "/transactional/content-preview": {
      "post": {
        "summary": "Preview a template with JSON attributes",
        "description": "Renders saved content without sending mail or consuming sending quota. Uses the same renderer as template sends.",
        "tags": [
          "Application templates"
        ],
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ],
        "security": [
          {
            "ApiKeyAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "X-Workspace-ID",
            "in": "header",
            "required": false,
            "type": "string",
            "format": "uuid",
            "description": "Required with a JWT for workspace operations. Omit with an API key: its workspace is fixed; conflicting or duplicate headers are rejected.",
            "x-example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
          },
          {
            "name": "request",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/TemplatePreviewRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Rendered email",
            "schema": {
              "$ref": "#/definitions/TemplatePreviewResult"
            }
          },
          "400": {
            "description": "Invalid fields, JSON, variable syntax or values, or rendered size"
          },
          "401": {
            "description": "Invalid authentication"
          },
          "404": {
            "description": "Template not found in this workspace"
          },
          "413": {
            "description": "Request body exceeds 576 KiB"
          },
          "503": {
            "description": "Temporarily unavailable"
          }
        },
        "x-required-scope": "templates:read"
      }
    }
  },
  "definitions": {
    "ApplicationSendRequest": {
      "type": "object",
      "properties": {
        "analytics": {
          "type": "boolean",
          "default": false,
          "description": "Track opens for this send. Requires HTML; defaults to false.",
          "example": false
        },
        "recipient_timezone": {
          "type": "string",
          "maxLength": 128,
          "description": "Recipient IANA time zone. Requires analytics=true; the API does not infer it.",
          "example": "America/Chicago"
        },
        "from_email": {
          "type": "string",
          "description": "Sender address. If omitted, uses the workspace sender address.",
          "example": "hello@example.com"
        },
        "from_name": {
          "type": "string",
          "description": "Sender name shown beside the email address.",
          "example": "Example Studio"
        },
        "html": {
          "type": "string",
          "description": "Optional text/html body. Supply HTML, plain text, or both. HTML-only sends include a generated text alternative.",
          "example": "<p>Your order is ready.</p>"
        },
        "reply_to": {
          "type": "string",
          "description": "Address for replies. Defaults to the sender address.",
          "example": "replies@example.com"
        },
        "subject": {
          "type": "string",
          "description": "Subject line, up to 998 UTF-8 bytes after rendering. Template variables use attributes. Blanks and line breaks are not allowed.",
          "example": "Your September update"
        },
        "tags": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "description": "Metadata you can use to identify or filter the send.",
          "example": {
            "order_id": "A-1042"
          }
        },
        "text": {
          "type": "string",
          "description": "Optional authored text/plain alternative, preserved when HTML is also present. Supply HTML, plain text, or both; HTML-only sends generate plain text at delivery.",
          "example": "Your order is ready."
        },
        "to": {
          "type": "string",
          "description": "Recipient email address.",
          "example": "alex@example.com"
        },
        "template_id": {
          "type": "string",
          "format": "uuid",
          "description": "Saved custom or system template in this workspace. Use instead of html and text. Save a copy of a shared starter first.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
        },
        "attributes": {
          "type": "object",
          "additionalProperties": true,
          "description": "Template data, up to 16 KiB. Use double-brace names or paths such as {{order.number}}. Referenced values must be strings, numbers, or booleans; missing or null values fail. Requires template_id.",
          "example": {
            "order": {
              "number": "A-1042"
            }
          }
        }
      },
      "required": [
        "to",
        "subject"
      ],
      "description": "Supply template_id and JSON attributes, or raw html/text bodies. Template requests render the subject and both saved parts; HTML uses contextual escaping and subject/text values remain literal. Raw-body requests are literal. At least one nonblank body is required; rendered bodies together are limited to 256 KiB. The rendered content is snapshotted at queue admission. Idempotency compares rendered content: template edits that change the output can make a retry return 409.",
      "additionalProperties": false,
      "example": {
        "to": "alex@example.com",
        "subject": "Your order A-1042 is ready",
        "html": "<p>Your order A-1042 is ready.</p>",
        "text": "Your order A-1042 is ready.",
        "tags": {
          "order_id": "A-1042"
        }
      }
    },
    "Automation": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Automation ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "workspace_id": {
          "type": "string",
          "description": "Workspace this resource belongs to.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "name": {
          "type": "string",
          "description": "Name of the automation.",
          "example": "Welcome series"
        },
        "status": {
          "type": "string",
          "description": "Current state of this resource.",
          "example": "draft"
        },
        "trigger_type": {
          "type": "string",
          "description": "Event that enrolls a contact in the automation.",
          "example": "manual"
        },
        "trigger_config": {
          "type": "object",
          "additionalProperties": true,
          "description": "Settings for the selected trigger. Manual triggers use an empty object.",
          "example": {}
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "description": "When this resource was last updated, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "workspace_id",
        "name",
        "status",
        "trigger_type",
        "trigger_config",
        "created_at",
        "updated_at"
      ]
    },
    "AutomationStep": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Step ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "automation_id": {
          "type": "string",
          "description": "ID of the automation.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "step_type": {
          "type": "string",
          "description": "Action this step performs.",
          "example": "end"
        },
        "config": {
          "type": "object",
          "additionalProperties": true,
          "description": "Settings for the selected step type.",
          "example": {}
        },
        "next_step_id": {
          "type": "string",
          "description": "ID of the next step. Omit when this step ends the path.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "yes_step_id": {
          "type": "string",
          "description": "Next step when the condition matches.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "no_step_id": {
          "type": "string",
          "description": "Next step when the condition does not match.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "sort_order": {
          "type": "integer",
          "description": "Step position. The lowest position is the entry step.",
          "example": 0
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "automation_id",
        "step_type",
        "config",
        "sort_order",
        "created_at"
      ],
      "example": {
        "id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
        "automation_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
        "step_type": "end",
        "config": {},
        "sort_order": 0,
        "created_at": "2026-09-27T12:00:00Z"
      }
    },
    "AutomationWithSteps": {
      "allOf": [
        {
          "$ref": "#/definitions/Automation"
        },
        {
          "type": "object",
          "properties": {
            "steps": {
              "type": "array",
              "items": {
                "$ref": "#/definitions/AutomationStep"
              },
              "description": "Steps in this automation."
            }
          },
          "required": [
            "steps"
          ]
        }
      ]
    },
    "Campaign": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Campaign ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "workspace_id": {
          "type": "string",
          "description": "Workspace this resource belongs to.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "name": {
          "type": "string",
          "description": "Internal campaign name. Your recipients do not see it.",
          "example": "September newsletter"
        },
        "subject": {
          "type": "string",
          "description": "Subject line your recipients see.",
          "example": "Your September update"
        },
        "status": {
          "type": "string",
          "description": "Current state of this resource.",
          "example": "draft"
        },
        "template_id": {
          "type": "string",
          "description": "ID of the saved template to use.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "from_name": {
          "type": "string",
          "description": "Sender name shown beside the email address.",
          "example": "Example Studio"
        },
        "from_email": {
          "type": "string",
          "description": "Email address shown as the sender.",
          "example": "hello@example.com"
        },
        "reply_to": {
          "type": "string",
          "description": "Email address that receives replies.",
          "example": "replies@example.com"
        },
        "html_body": {
          "type": "string",
          "description": "Email content in HTML.",
          "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
        },
        "text_body": {
          "type": "string",
          "description": "Plain text version of the email.",
          "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
        },
        "preview_text": {
          "type": "string",
          "description": "Short text shown beside the subject in an inbox.",
          "example": "A few things we made this month."
        },
        "json_design": {
          "type": "object",
          "additionalProperties": true,
          "description": "Editor design data used to reopen the email in the builder.",
          "example": {}
        },
        "category_id": {
          "type": "string",
          "format": "uuid",
          "description": "Subscription category for this campaign.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
        },
        "total_recipients": {
          "type": "integer",
          "description": "Number of recipients in the campaign.",
          "example": 100
        },
        "scheduled_at": {
          "type": "string",
          "description": "When sending is scheduled to start, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "description": "When this resource was last updated, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "workspace_id",
        "name",
        "status",
        "total_recipients",
        "created_at",
        "updated_at"
      ],
      "example": {
        "id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
        "workspace_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
        "name": "September newsletter",
        "subject": "Your September update",
        "status": "draft",
        "from_name": "Example Studio",
        "from_email": "hello@example.com",
        "reply_to": "replies@example.com",
        "html_body": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>",
        "text_body": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}",
        "preview_text": "A few things we made this month.",
        "total_recipients": 0,
        "created_at": "2026-09-27T12:00:00Z",
        "updated_at": "2026-09-27T12:00:00Z"
      }
    },
    "Template": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Template ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "workspace_id": {
          "type": "string",
          "description": "Workspace this resource belongs to.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "name": {
          "type": "string",
          "description": "Name of the saved template.",
          "example": "Monthly newsletter"
        },
        "description": {
          "type": "string",
          "description": "A short note to help you recognize this resource.",
          "example": "Monthly product updates."
        },
        "html_body": {
          "type": "string",
          "description": "Email content in HTML.",
          "example": "<p>Hello!</p><p>{{physical_address}}</p><a href=\"{{unsubscribe_url}}\">Unsubscribe</a>"
        },
        "text_body": {
          "type": "string",
          "description": "Plain text version of the email.",
          "example": "Hello!\n{{physical_address}}\nUnsubscribe: {{unsubscribe_url}}"
        },
        "json_design": {
          "type": "object",
          "additionalProperties": true,
          "description": "Editor design data used to reopen the email in the builder.",
          "example": {}
        },
        "category": {
          "type": "string",
          "description": "Template category.",
          "example": "custom"
        },
        "thumbnail_url": {
          "type": "string",
          "description": "URL of the template preview image. Omitted for API-key requests.",
          "example": "https://example.com/newsletter.png"
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "description": "When this resource was last updated, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "workspace_id",
        "name",
        "category",
        "created_at",
        "updated_at"
      ]
    },
    "TemplatePreviewRequest": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "template_id",
        "subject"
      ],
      "properties": {
        "template_id": {
          "type": "string",
          "format": "uuid",
          "description": "Saved custom or system template in this workspace. Use instead of html and text. Save a copy of a shared starter first.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423"
        },
        "subject": {
          "type": "string",
          "description": "Subject line, up to 998 UTF-8 bytes after rendering. Template variables use attributes. Blanks and line breaks are not allowed.",
          "example": "Your September update"
        },
        "attributes": {
          "type": "object",
          "additionalProperties": true,
          "description": "Template data, up to 16 KiB. Use double-brace names or paths such as {{order.number}}. Referenced values must be strings, numbers, or booleans; missing or null values fail. Requires template_id.",
          "example": {
            "order": {
              "number": "A-1042"
            }
          }
        }
      },
      "example": {
        "template_id": "7d264eba-7fe7-4b28-9d46-830beadcc423",
        "subject": "Order {{order.number}} is ready",
        "attributes": {
          "order": {
            "number": "A-1042"
          }
        }
      }
    },
    "TemplatePreviewResult": {
      "type": "object",
      "required": [
        "subject",
        "html",
        "text"
      ],
      "properties": {
        "subject": {
          "type": "string",
          "description": "Subject line your recipients see.",
          "example": "Order A-1042 is ready"
        },
        "html": {
          "type": "string",
          "description": "Email content in HTML.",
          "example": "<p>Your order A-1042 is ready.</p>"
        },
        "text": {
          "type": "string",
          "description": "Plain text version of the email.",
          "example": "Your order A-1042 is ready."
        }
      },
      "description": "Rendered saved content. Empty text means no authored text alternative; the HTML-only text fallback is generated at delivery."
    },
    "UserProfile": {
      "type": "object",
      "properties": {
        "avatar_url": {
          "type": "string",
          "description": "Profile image URL. Omitted when no image is set.",
          "example": "https://example.com/alex.png"
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "email": {
          "type": "string",
          "description": "Email address for your account.",
          "example": "alex@example.com"
        },
        "email_verified": {
          "type": "boolean",
          "description": "Whether your email address has been confirmed.",
          "example": true
        },
        "id": {
          "type": "string",
          "description": "User ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "name": {
          "type": "string",
          "description": "Your display name.",
          "example": "Alex Morgan"
        },
        "company_name": {
          "type": "string",
          "description": "Company name on your profile.",
          "example": "Example Studio"
        },
        "has_password": {
          "type": "boolean",
          "description": "Whether your account has a password.",
          "example": true
        }
      },
      "required": [
        "id",
        "email",
        "name",
        "company_name",
        "email_verified",
        "has_password",
        "created_at"
      ]
    },
    "Webhook": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Webhook endpoint ID.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "workspace_id": {
          "type": "string",
          "description": "Workspace this resource belongs to.",
          "example": "7d264eba-7fe7-4b28-9d46-830beadcc423",
          "format": "uuid"
        },
        "url": {
          "type": "string",
          "description": "Public HTTPS address that receives webhook events.",
          "example": "https://example.com/webhooks/getread"
        },
        "description": {
          "type": "string",
          "x-nullable": true,
          "description": "A short note to help you recognize this resource.",
          "example": "Monthly product updates."
        },
        "events": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Event names you want this endpoint to receive.",
          "example": [
            "campaign.sent"
          ]
        },
        "status": {
          "type": "string",
          "description": "Current state of this resource.",
          "example": "active"
        },
        "created_at": {
          "type": "string",
          "description": "When this resource was created, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        },
        "updated_at": {
          "type": "string",
          "description": "When this resource was last updated, in UTC.",
          "example": "2026-09-27T12:00:00Z",
          "format": "date-time"
        }
      },
      "required": [
        "id",
        "workspace_id",
        "url",
        "description",
        "events",
        "status",
        "created_at",
        "updated_at"
      ]
    },
    "WebhookWithSecret": {
      "allOf": [
        {
          "$ref": "#/definitions/Webhook"
        },
        {
          "type": "object",
          "properties": {
            "secret": {
              "type": "string",
              "description": "Signing secret, shown once on creation or rotation. Store it on your server.",
              "example": "<webhook-signing-secret>"
            }
          },
          "required": [
            "secret"
          ]
        }
      ]
    }
  },
  "securityDefinitions": {
    "BearerAuth": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "JWT access token: Bearer <token>. Workspace operations also require X-Workspace-ID."
    },
    "ApiKeyAuth": {
      "type": "apiKey",
      "in": "header",
      "name": "Authorization",
      "description": "Workspace API key: Bearer <key>. Requires the operation’s x-required-scope; workspace is derived from the key. Legacy source keys retain transactional send/preview access only."
    }
  }
}
