{
  "openapi": "3.1.0",
  "info": {
    "title": "BioFlow API",
    "version": "1.0.0",
    "description": "The BioFlow public REST API. Authenticate with a bf_live_/bf_test_ API key — as `Authorization: Bearer <key>` or `x-api-key: <key>`. Errors are RFC 9457 problem+json with a stable `code`.",
    "contact": {
      "email": "support@getbioflow.com"
    }
  },
  "servers": [
    {
      "url": "https://app.getbioflow.com"
    }
  ],
  "security": [
    {
      "apiKeyBearer": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "paths": {
    "/v1/analytics/summary": {
      "get": {
        "operationId": "getAnalyticsSummary",
        "summary": "Get analytics summary",
        "description": "Workspace analytics for the last 7/30/90 days: views, clicks, unique visitors, CTR, top links, top referrers, and tip revenue.\n\nRequires scope: analytics:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "analytics:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "query",
            "name": "range_days",
            "schema": {
              "default": 30,
              "type": "integer",
              "minimum": -9007199254740991,
              "maximum": 9007199254740991
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The analytics summary",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AnalyticsSummary"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "operationId": "listContacts",
        "summary": "List contacts",
        "description": "Captured contacts and leads (newsletter signups, form submissions, gated downloads), newest first. Cursor-paginated with REAL database keyset cursors — safe at any collection size.\n\nRequires scope: contacts:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "contacts:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "after",
            "schema": {
              "description": "Opaque cursor from a previous response",
              "type": "string"
            },
            "description": "Opaque cursor from a previous response"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of contacts",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/files": {
      "get": {
        "operationId": "listFiles",
        "summary": "List files",
        "description": "The workspace's uploaded files (name, MIME type, size, public path), newest first. Pass a file's public_path as file_url to Add block to wire it into IMAGE/FILE/CAROUSEL/PRODUCT blocks.\n\nRequires scope: files:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "files:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "after",
            "schema": {
              "description": "Opaque cursor from a previous response",
              "type": "string"
            },
            "description": "Opaque cursor from a previous response"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of files",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileList"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pages": {
      "get": {
        "operationId": "listPages",
        "summary": "List pages",
        "description": "Every bio page in the workspace, newest-updated first. Cursor-paginated.\n\nRequires scope: pages:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "after",
            "schema": {
              "description": "Opaque cursor from a previous response",
              "type": "string"
            },
            "description": "Opaque cursor from a previous response"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of pages",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageList"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPage",
        "summary": "Create a page",
        "description": "Create a new bio page as an UNPUBLISHED draft — the same path as the dashboard's New page dialog (slug derived from the title and deduped). Nothing goes live until Publish page.\n\nRequires scope: pages:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePageRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created page",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pages/{page_id}": {
      "delete": {
        "operationId": "deletePage",
        "summary": "Delete a page",
        "description": "Permanently delete a page, its blocks, versions, and route. This cannot be undone.\n\nRequires scope: pages:write. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Page ID from List pages"
            },
            "required": true,
            "description": "Page ID from List pages"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted — no content",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getPage",
        "summary": "Get a page",
        "description": "One page's draft AND published state: ordered draft block refs (IDs for the write endpoints), theme, route, and the draft.updated_at concurrency stamp every write requires.\n\nRequires scope: pages:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Page ID from List pages"
            },
            "required": true,
            "description": "Page ID from List pages"
          }
        ],
        "responses": {
          "200": {
            "description": "The page",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updatePage",
        "summary": "Update a page draft",
        "description": "Merge-patch the DRAFT: title, description, theme preset, per-block data patches, and/or full reorder via block_order — everything unmentioned is preserved. Requires expected_updated_at; a stale stamp is refused with 409 stale_snapshot.\n\nRequires scope: pages:write. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Page ID from List pages"
            },
            "required": true,
            "description": "Page ID from List pages"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated page",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pages/{page_id}/blocks": {
      "post": {
        "operationId": "addBlock",
        "summary": "Add a block",
        "description": "Append ONE block to the page DRAFT, preserving every existing block byte-for-byte. Optionally wire an uploaded file (public_path from List files) into IMAGE/FILE/CAROUSEL/PRODUCT blocks. Requires expected_updated_at.\n\nRequires scope: pages:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Page ID from List pages"
            },
            "required": true,
            "description": "Page ID from List pages"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddBlockRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The page with the new block",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pages/{page_id}/blocks/{block_id}": {
      "delete": {
        "operationId": "removeBlock",
        "summary": "Remove a block",
        "description": "Delete one block from the page DRAFT, preserving everything else. Removing the last remaining block is refused. Requires expected_updated_at (query parameter).\n\nRequires scope: pages:write. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true
          },
          {
            "in": "path",
            "name": "block_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Block ID from the page's draft.blocks"
            },
            "required": true,
            "description": "Block ID from the page's draft.blocks"
          },
          {
            "in": "query",
            "name": "expected_updated_at",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Concurrency stamp: the draft.updated_at you last read. A mismatch is refused with 409 stale_snapshot — re-read the page and retry."
            },
            "required": true,
            "description": "Concurrency stamp: the draft.updated_at you last read. A mismatch is refused with 409 stale_snapshot — re-read the page and retry."
          }
        ],
        "responses": {
          "200": {
            "description": "The page without the block",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/pages/{page_id}/publish": {
      "post": {
        "operationId": "publishPage",
        "summary": "Publish a page",
        "description": "Publish the page's current DRAFT to its live public route — the same code path as the editor's Publish button. Pass starts_at to schedule the publish instead of applying it now. Requires the publish scope, granted separately at key creation.\n\nRequires scope: publish. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "publish"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "page_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Page ID from List pages"
            },
            "required": true,
            "description": "Page ID from List pages"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishPageRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The published (or scheduled) page",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishResult"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage": {
      "get": {
        "operationId": "getUsage",
        "summary": "Get API usage",
        "description": "Current billing-period API usage: requests used/remaining against the plan's monthly quota, the reset instant, and the per-key burst limit. Polling this endpoint never consumes quota.\n\nRequires scope: pages:read or pages:write or analytics:read or contacts:read or files:read or publish. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "pages:read",
          "pages:write",
          "analytics:read",
          "contacts:read",
          "files:read",
          "publish"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 0,
        "x-idempotent": false,
        "responses": {
          "200": {
            "description": "Current usage",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints": {
      "get": {
        "operationId": "listWebhookEndpoints",
        "summary": "List webhook endpoints",
        "description": "Every webhook endpoint in the workspace (at most 10 — no pagination). Signing secrets are never included.\n\nRequires scope: webhooks:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "responses": {
          "200": {
            "description": "The endpoints",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointList"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookEndpoint",
        "summary": "Create a webhook endpoint",
        "description": "Register a public HTTPS URL for event delivery. The URL is SSRF-screened, then must accept a SIGNED endpoint.test event with 2xx before anything is stored. The response carries the whsec_ signing secret exactly once. Deliveries are signed per Standard Webhooks (webhook-id / webhook-timestamp / webhook-signature over `id.timestamp.rawBody`), retried with exponential backoff for ~41 hours, and the endpoint auto-disables after 20 consecutive failures.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created endpoint and its signing secret (shown once)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWebhookEndpointResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}": {
      "delete": {
        "operationId": "deleteWebhookEndpoint",
        "summary": "Delete a webhook endpoint",
        "description": "Permanently delete the endpoint and its delivery history. This cannot be undone.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted — no content",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getWebhookEndpoint",
        "summary": "Get a webhook endpoint",
        "description": "Requires scope: webhooks:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWebhookEndpoint",
        "summary": "Update a webhook endpoint",
        "description": "Change the URL (re-verified with a signed test event first), the subscribed event types, or enable/disable delivery. Re-enabling resets the consecutive-failure counter; missed events can then be re-queued with Replay failed deliveries.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookEndpointRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated endpoint",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}/deliveries": {
      "get": {
        "operationId": "listWebhookDeliveries",
        "summary": "List deliveries",
        "description": "The endpoint's delivery log, newest first, cursor-paginated, with per-attempt status codes, bounded error summaries, and the next automatic retry time.\n\nRequires scope: webhooks:read. Plan entitlement: public_api (Creator and Pro).",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:read"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": false,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          },
          {
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "in": "query",
            "name": "after",
            "schema": {
              "description": "Opaque cursor from a previous response",
              "type": "string"
            },
            "description": "Opaque cursor from a previous response"
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "SUCCEEDED",
                "FAILED"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/resend": {
      "post": {
        "operationId": "resendWebhookDelivery",
        "summary": "Resend a delivery",
        "description": "Re-queue ONE delivery for immediate redelivery, restarting its retry ladder. The webhook-id stays the same — consumers deduplicate on it.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": true
          },
          {
            "in": "path",
            "name": "delivery_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Delivery ID from List deliveries"
            },
            "required": true,
            "description": "Delivery ID from List deliveries"
          }
        ],
        "responses": {
          "200": {
            "description": "The re-queued delivery",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDelivery"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}/replay": {
      "post": {
        "operationId": "replayWebhookDeliveries",
        "summary": "Replay failed deliveries",
        "description": "Bulk recovery: re-queue every FAILED delivery created since the given instant (last 30 days). Use after re-enabling an auto-disabled endpoint.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplayWebhooksRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "How many deliveries were re-queued",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookReplayResult"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}/rotate-secret": {
      "post": {
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "description": "Mint a NEW whsec_ secret (returned once). For 24 hours deliveries carry TWO signatures — the new and the previous secret — so you can roll your verifier without dropping events.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "responses": {
          "200": {
            "description": "The endpoint and its new secret (shown once)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateWebhookSecretResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhook-endpoints/{endpoint_id}/test": {
      "post": {
        "operationId": "testWebhookEndpoint",
        "summary": "Send a test event",
        "description": "Synchronously send a signed endpoint.test event to the endpoint and report the outcome. Does not touch the delivery log or failure counters.\n\nRequires scope: webhooks:write. Plan entitlement: public_api (Creator and Pro).\n\nConsequential operation — send an Idempotency-Key header.",
        "security": [
          {
            "apiKeyBearer": []
          },
          {
            "apiKeyHeader": []
          }
        ],
        "x-scopes": [
          "webhooks:write"
        ],
        "x-entitlement": "public_api",
        "x-meter-cost": 1,
        "x-idempotent": true,
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Endpoint ID from List webhook endpoints"
            },
            "required": true,
            "description": "Endpoint ID from List webhook endpoints"
          }
        ],
        "responses": {
          "200": {
            "description": "The test outcome",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              },
              "RateLimit-Policy": {
                "description": "IETF draft-11 rate-limit policy (structured field).",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit": {
                "description": "IETF draft-11 rate-limit state (structured field).",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                }
              }
            }
          },
          "400": {
            "description": "Validation failed (invalid_request)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (invalid_api_key)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Denied: insufficient_scope, feature_not_enabled, or test_key_read_only",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited: rate_limited (per-key burst) or quota_exhausted (monthly)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected failure (internal_error)",
            "headers": {
              "X-Request-Id": {
                "description": "Unique request identifier — quote it in support requests.",
                "schema": {
                  "type": "string",
                  "example": "req_01abc"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CreatePageRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 2,
            "maxLength": 80
          },
          "theme_preset_key": {
            "description": "One of the 13 canonical theme preset keys",
            "type": "string",
            "minLength": 1
          },
          "header_layout": {
            "type": "string",
            "enum": [
              "classic",
              "banner",
              "hero",
              "cutout"
            ]
          }
        },
        "required": [
          "title"
        ]
      },
      "UpdatePageRequest": {
        "type": "object",
        "properties": {
          "expected_updated_at": {
            "type": "string",
            "minLength": 1,
            "description": "Concurrency stamp: the draft.updated_at you last read. A mismatch is refused with 409 stale_snapshot — re-read the page and retry."
          },
          "title": {
            "type": "string",
            "minLength": 2,
            "maxLength": 80
          },
          "description": {
            "type": "string",
            "maxLength": 180
          },
          "theme_preset_key": {
            "type": "string",
            "minLength": 1
          },
          "block_updates": {
            "minItems": 1,
            "maxItems": 20,
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "block_id": {
                  "type": "string",
                  "minLength": 1
                },
                "data": {
                  "type": "object",
                  "propertyNames": {
                    "type": "string"
                  },
                  "additionalProperties": {},
                  "description": "Fields to merge into the block (partial)"
                }
              },
              "required": [
                "block_id",
                "data"
              ]
            }
          },
          "block_order": {
            "description": "Every existing block ID exactly once, in the new top-to-bottom order",
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            }
          }
        },
        "required": [
          "expected_updated_at"
        ]
      },
      "AddBlockRequest": {
        "type": "object",
        "properties": {
          "expected_updated_at": {
            "type": "string",
            "minLength": 1,
            "description": "Concurrency stamp: the draft.updated_at you last read. A mismatch is refused with 409 stale_snapshot — re-read the page and retry."
          },
          "kind": {
            "type": "string",
            "minLength": 1,
            "description": "Block kind, e.g. LINK"
          },
          "data": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {}
          },
          "file_url": {
            "description": "public_path of a workspace file from List files",
            "type": "string"
          },
          "file_name": {
            "type": "string"
          }
        },
        "required": [
          "expected_updated_at",
          "kind"
        ]
      },
      "PublishPageRequest": {
        "type": "object",
        "properties": {
          "starts_at": {
            "description": "Omit to publish now; an ISO instant schedules the publish instead",
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          }
        }
      },
      "CreateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public HTTPS URL on port 443. Verified with a signed endpoint.test event before the endpoint is created — respond 2xx."
          },
          "event_types": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "page.published",
                "sale.paid",
                "sale.refunded"
              ],
              "description": "A subscribable event type"
            }
          }
        },
        "required": [
          "url",
          "event_types"
        ]
      },
      "UpdateWebhookEndpointRequest": {
        "type": "object",
        "properties": {
          "url": {
            "description": "New URL — re-verified with a signed test event first",
            "type": "string",
            "format": "uri"
          },
          "event_types": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "page.published",
                "sale.paid",
                "sale.refunded"
              ],
              "description": "A subscribable event type"
            }
          },
          "enabled": {
            "description": "true re-enables a disabled endpoint (and resets its failure count); false disables it",
            "type": "boolean"
          }
        }
      },
      "ReplayWebhooksRequest": {
        "type": "object",
        "properties": {
          "since": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "description": "Re-queue every FAILED delivery created at or after this instant (last 30 days)"
          }
        },
        "required": [
          "since"
        ]
      },
      "AnalyticsSummary": {
        "type": "object",
        "properties": {
          "range_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "totals": {
            "type": "object",
            "properties": {
              "views": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "clicks": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "unique_visitors": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "ctr_percent": {
                "type": "number"
              }
            },
            "required": [
              "views",
              "clicks",
              "unique_visitors",
              "ctr_percent"
            ],
            "additionalProperties": false
          },
          "top_links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "clicks": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "page_title": {
                  "type": "string"
                }
              },
              "required": [
                "label",
                "url",
                "clicks",
                "page_title"
              ],
              "additionalProperties": false
            }
          },
          "top_referrers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "label": {
                  "type": "string"
                },
                "views": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "label",
                "views"
              ],
              "additionalProperties": false
            }
          },
          "tips": {
            "type": "object",
            "properties": {
              "count": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "total_gross_cents": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "refunded_count": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "unique_fans": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              "currency": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "count",
              "total_gross_cents",
              "refunded_count",
              "unique_fans",
              "currency"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "range_days",
          "totals",
          "top_links",
          "top_referrers",
          "tips"
        ],
        "additionalProperties": false
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Docs URL, https://getbioflow.com/docs/api/errors/<code>"
          },
          "title": {
            "type": "string",
            "description": "Human summary — never parse"
          },
          "status": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "HTTP status, mirrored in the body"
          },
          "detail": {
            "description": "Human detail — never parse",
            "type": "string"
          },
          "instance": {
            "type": "string",
            "example": "urn:request:req_01abc"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_api_key",
              "insufficient_scope",
              "feature_not_enabled",
              "test_key_read_only",
              "resource_not_found",
              "stale_snapshot",
              "idempotency_in_progress",
              "idempotency_key_reused",
              "endpoint_verification_failed",
              "endpoint_limit_reached",
              "rate_limited",
              "quota_exhausted",
              "internal_error"
            ],
            "description": "The stable machine-readable code — branch on this"
          },
          "request_id": {
            "type": "string",
            "example": "req_01abc"
          },
          "errors": {
            "description": "Field-level validation errors (400 only)",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "pointer": {
                  "type": "string",
                  "example": "/title"
                },
                "code": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "pointer",
                "code",
                "message"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "instance",
          "code",
          "request_id"
        ],
        "additionalProperties": false,
        "description": "RFC 9457 problem details"
      },
      "ContactList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "source": {
            "type": "string"
          },
          "source_block_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "example": "2026-07-20T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "source",
          "source_block_id",
          "created_at"
        ],
        "additionalProperties": false
      },
      "FileList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/File"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "File": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "mime_type": {
            "type": "string"
          },
          "public_path": {
            "type": "string"
          },
          "download_path": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "example": "2026-07-20T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "mime_type",
          "public_path",
          "download_path",
          "size_bytes",
          "created_at"
        ],
        "additionalProperties": false
      },
      "PageList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PageSummary"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "PageSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable opaque page ID"
          },
          "title": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PUBLISHED",
              "ARCHIVED"
            ]
          },
          "block_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "public_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Live URL when routed; null for unrouted drafts"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "example": "2026-07-20T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "title",
          "slug",
          "status",
          "block_count",
          "public_url",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "Page": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "DRAFT",
              "PUBLISHED",
              "ARCHIVED"
            ]
          },
          "locale": {
            "type": "string"
          },
          "public_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Live URL when routed; null for unrouted drafts"
          },
          "theme": {
            "type": "object",
            "properties": {
              "label": {
                "type": "string"
              },
              "preset_key": {
                "type": "string"
              }
            },
            "required": [
              "label",
              "preset_key"
            ],
            "additionalProperties": false
          },
          "draft": {
            "type": "object",
            "properties": {
              "updated_at": {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
                "example": "2026-07-20T12:00:00.000Z",
                "description": "Concurrency stamp — pass as expected_updated_at on every write"
              },
              "block_count": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "blocks": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/PageBlockRef"
                }
              }
            },
            "required": [
              "updated_at",
              "block_count",
              "blocks"
            ],
            "additionalProperties": false
          },
          "published": {
            "type": "object",
            "properties": {
              "is_live": {
                "type": "boolean"
              },
              "block_count": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "live_updated_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
                    "example": "2026-07-20T12:00:00.000Z"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "is_live",
              "block_count",
              "live_updated_at"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "title",
          "description",
          "slug",
          "status",
          "locale",
          "public_url",
          "theme",
          "draft",
          "published"
        ],
        "additionalProperties": false
      },
      "PageBlockRef": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "label": {
            "type": "string",
            "description": "Display label derived from data"
          }
        },
        "required": [
          "id",
          "kind",
          "enabled",
          "label"
        ],
        "additionalProperties": false
      },
      "PublishResult": {
        "type": "object",
        "properties": {
          "page": {
            "$ref": "#/components/schemas/Page"
          },
          "scheduled_for": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
                "example": "2026-07-20T12:00:00.000Z"
              },
              {
                "type": "null"
              }
            ],
            "description": "Set when the publish was scheduled, not applied"
          }
        },
        "required": [
          "page",
          "scheduled_for"
        ],
        "additionalProperties": false
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "description": "Workspace plan id, e.g. CREATOR"
          },
          "period_start": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "example": "2026-07-20T12:00:00.000Z"
          },
          "period_end": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "example": "2026-07-20T12:00:00.000Z",
            "description": "When the meter resets"
          },
          "meters": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "example": "api_requests"
                },
                "used": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "limit": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "remaining": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                }
              },
              "required": [
                "name",
                "used",
                "limit",
                "remaining"
              ],
              "additionalProperties": false
            }
          },
          "burst": {
            "type": "object",
            "properties": {
              "per_minute": {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991,
                "description": "Per-key burst limit for this plan"
              }
            },
            "required": [
              "per_minute"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "plan",
          "period_start",
          "period_end",
          "meters",
          "burst"
        ],
        "additionalProperties": false
      },
      "WebhookEndpointList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEndpoint"
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false
      },
      "WebhookEndpoint": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable opaque endpoint ID"
          },
          "url": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "DISABLED"
            ]
          },
          "disabled_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "page.published",
                "sale.paid",
                "sale.refunded"
              ],
              "description": "A subscribable event type"
            }
          },
          "consecutive_failures": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "last_success_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ]
          },
          "last_failure_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ]
          },
          "previous_secret_expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "While set, the pre-rotation secret still signs deliveries (second signature)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          }
        },
        "required": [
          "id",
          "url",
          "status",
          "disabled_reason",
          "event_types",
          "consecutive_failures",
          "last_success_at",
          "last_failure_at",
          "previous_secret_expires_at",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "description": "A webhook endpoint. The whsec_ signing secret is returned ONLY by Create and Rotate secret — never here."
      },
      "CreateWebhookEndpointResponse": {
        "type": "object",
        "properties": {
          "endpoint": {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          "secret": {
            "type": "string",
            "description": "The whsec_ signing secret — shown ONCE, store it now. Verify webhook-signature with it per Standard Webhooks."
          }
        },
        "required": [
          "endpoint",
          "secret"
        ],
        "additionalProperties": false
      },
      "WebhookDeliveryList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "event_id": {
            "type": "string"
          },
          "event_type": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "PENDING",
              "SUCCEEDED",
              "FAILED"
            ]
          },
          "attempt_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "next_attempt_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the next automatic attempt is due (PENDING only)"
          },
          "last_status_code": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          },
          "attempts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookAttempt"
            }
          }
        },
        "required": [
          "id",
          "event_id",
          "event_type",
          "status",
          "attempt_count",
          "next_attempt_at",
          "last_status_code",
          "created_at",
          "attempts"
        ],
        "additionalProperties": false
      },
      "WebhookAttempt": {
        "type": "object",
        "properties": {
          "number": {
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "duration_ms": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          },
          "at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          }
        },
        "required": [
          "number",
          "status_code",
          "error",
          "duration_ms",
          "at"
        ],
        "additionalProperties": false
      },
      "WebhookReplayResult": {
        "type": "object",
        "properties": {
          "replayed": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "replayed"
        ],
        "additionalProperties": false
      },
      "RotateWebhookSecretResponse": {
        "type": "object",
        "properties": {
          "endpoint": {
            "$ref": "#/components/schemas/WebhookEndpoint"
          },
          "secret": {
            "type": "string",
            "description": "The NEW whsec_ signing secret — shown once, store it now"
          },
          "previous_secret_expires_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
            "description": "Until then the old secret also signs (second signature)"
          }
        },
        "required": [
          "endpoint",
          "secret",
          "previous_secret_expires_at"
        ],
        "additionalProperties": false
      },
      "WebhookTestResult": {
        "type": "object",
        "properties": {
          "delivered": {
            "type": "boolean"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "delivered",
          "status_code",
          "error"
        ],
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "apiKeyBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key (bf_live_… / bf_test_…) as a Bearer token."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "API key (bf_live_… / bf_test_…) in the x-api-key header."
      }
    }
  },
  "x-bioflow-problems": [
    {
      "code": "invalid_request",
      "status": 400,
      "title": "The request body or parameters failed validation",
      "type": "https://getbioflow.com/docs/api/errors/invalid-request"
    },
    {
      "code": "invalid_api_key",
      "status": 401,
      "title": "Missing, malformed, unknown, disabled, or expired API key",
      "type": "https://getbioflow.com/docs/api/errors/invalid-api-key"
    },
    {
      "code": "insufficient_scope",
      "status": 403,
      "title": "The API key was not granted the required scope",
      "type": "https://getbioflow.com/docs/api/errors/insufficient-scope"
    },
    {
      "code": "feature_not_enabled",
      "status": 403,
      "title": "The workspace plan does not include public API access",
      "type": "https://getbioflow.com/docs/api/errors/feature-not-enabled"
    },
    {
      "code": "test_key_read_only",
      "status": 403,
      "title": "Test-mode keys are restricted to read operations",
      "type": "https://getbioflow.com/docs/api/errors/test-key-read-only"
    },
    {
      "code": "resource_not_found",
      "status": 404,
      "title": "No resource with that ID exists in this workspace",
      "type": "https://getbioflow.com/docs/api/errors/resource-not-found"
    },
    {
      "code": "stale_snapshot",
      "status": 409,
      "title": "The draft changed since it was last read",
      "type": "https://getbioflow.com/docs/api/errors/stale-snapshot"
    },
    {
      "code": "idempotency_in_progress",
      "status": 409,
      "title": "A request with this Idempotency-Key is still executing",
      "type": "https://getbioflow.com/docs/api/errors/idempotency-in-progress"
    },
    {
      "code": "idempotency_key_reused",
      "status": 422,
      "title": "This Idempotency-Key was already used with a different request",
      "type": "https://getbioflow.com/docs/api/errors/idempotency-key-reused"
    },
    {
      "code": "endpoint_verification_failed",
      "status": 422,
      "title": "The webhook endpoint did not accept the signed test event",
      "type": "https://getbioflow.com/docs/api/errors/endpoint-verification-failed"
    },
    {
      "code": "endpoint_limit_reached",
      "status": 422,
      "title": "The workspace webhook endpoint limit was reached",
      "type": "https://getbioflow.com/docs/api/errors/endpoint-limit-reached"
    },
    {
      "code": "rate_limited",
      "status": 429,
      "title": "Per-key rate limit exceeded",
      "type": "https://getbioflow.com/docs/api/errors/rate-limited"
    },
    {
      "code": "quota_exhausted",
      "status": 429,
      "title": "Monthly API quota exhausted",
      "type": "https://getbioflow.com/docs/api/errors/quota-exhausted"
    },
    {
      "code": "internal_error",
      "status": 500,
      "title": "Something went wrong on our side",
      "type": "https://getbioflow.com/docs/api/errors/internal-error"
    }
  ]
}
