{
  "openapi": "3.1.0",
  "info": {
    "title": "Zeodyn API",
    "version": "1.0.0",
    "description": "Public API for the Zeodyn™ platform. Assess AI agent commerce readiness across six dimensions of the Agent Commerce Stack™ framework.\n\n## Rate Limits\n\n| Endpoint | Limit | Window |\n|---|---|---|\n| `POST /api/scan` | 3 requests | 24 hours (per IP) |\n| `GET /api/pricing` | 100 requests | 1 hour (per IP) |\n| `GET /api/results/{id}` | No limit | — |\n| `GET /api/health` | No limit | — |\n\nWhen rate limited, responses include a `Retry-After` header (seconds).",
    "contact": {
      "name": "Zeodyn",
      "email": "hello@zeodyn.com",
      "url": "https://zeodyn.com/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://zeodyn.com/legal/terms"
    },
    "x-logo": {
      "url": "https://zeodyn.com/icon-512.png"
    }
  },
  "servers": [
    {
      "url": "https://zeodyn.com",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/scan": {
      "post": {
        "operationId": "scanUrl",
        "summary": "Scan a URL for AI agent commerce readiness",
        "description": "Submits a URL for assessment across six dimensions of the Agent Commerce Stack™. Returns a Zeodyn Score™ (1–100), dimension breakdowns, sub-check results, and prioritised recommendations. Free tier scans homepage only (1 page). Pro tier scans 2 pages (homepage + 1 product page). Growth tier scans up to 5 pages (homepage + up to 4 product pages). Product pages are discovered automatically. Rate limited to 3 scans per day per IP on the free tier.",
        "tags": [
          "Scanner"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScanRequest"
              },
              "example": {
                "url": "https://example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan completed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — malformed JSON, invalid URL, or blocked by SSRF protection.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid URL format"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the rate limit window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RateLimitError"
                }
              }
            }
          },
          "502": {
            "description": "Upstream error — the target URL may be unreachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Scan failed. The URL may be unreachable."
                }
              }
            }
          },
          "504": {
            "description": "Scan timed out (30-second limit).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Scan timed out. The URL may be unreachable or the page too large."
                }
              }
            }
          }
        }
      }
    },
    "/api/results/{id}": {
      "get": {
        "operationId": "getScanResult",
        "summary": "Retrieve a previous scan result",
        "description": "Fetches a previously completed scan result by its UUID. Results expire after 30 days.",
        "tags": [
          "Scanner"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "UUID of the scan result.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scan result found.",
            "headers": {
              "Cache-Control": {
                "description": "Private caching for 5 minutes.",
                "schema": {
                  "type": "string",
                  "const": "private, max-age=300"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid UUID format.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid result ID."
                }
              }
            }
          },
          "404": {
            "description": "Result not found or expired (30-day TTL).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Result not found or expired."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scan": {
      "post": {
        "operationId": "scanUrlAuthenticated",
        "summary": "Scan a URL (authenticated)",
        "description": "Submit a URL for scanning with Bearer token authentication. Returns a full Zeodyn Score™ with dimension breakdowns. Pro tier scans 2 pages (homepage + 1 product page). Growth tier scans up to 5 pages with automatic product page discovery. Rate limits based on subscription tier.",
        "tags": [
          "Scanner"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScanRequest"
              },
              "example": {
                "url": "https://example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scan completed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scan/{id}": {
      "get": {
        "operationId": "getAuthenticatedScanResult",
        "summary": "Retrieve a scan result (authenticated)",
        "description": "Retrieve a scan result by UUID. Only returns results owned by the authenticated user.",
        "tags": [
          "Scanner"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scan result returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanResult"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Scan not found or not owned by this user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scans": {
      "get": {
        "operationId": "listScans",
        "summary": "List scan history",
        "description": "List the authenticated user’s scan history with pagination.",
        "tags": [
          "Scanner"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Scan history returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ScanResult"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "offset": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/scan": {
      "post": {
        "operationId": "submitBatchScan",
        "summary": "Submit a batch scan (Growth+)",
        "description": "Submit up to 50 URLs for batch scanning. Returns immediately with a batch ID. URLs are processed asynchronously. Requires Growth tier or above.",
        "tags": [
          "Batch"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "urls"
                ],
                "properties": {
                  "urls": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "maxItems": 50
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              },
              "example": {
                "urls": [
                  "https://example.com",
                  "https://shop.example.com"
                ],
                "label": "Monthly check"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Batch scan accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batchId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "const": "pending"
                    },
                    "totalUrls": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Batch scanning requires Growth tier or above.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/scan/{id}": {
      "get": {
        "operationId": "getBatchScanStatus",
        "summary": "Check batch scan status (Growth+)",
        "description": "Retrieve status and per-URL results for a batch scan.",
        "tags": [
          "Batch"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch scan status returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "processing",
                        "completed",
                        "failed"
                      ]
                    },
                    "label": {
                      "type": "string"
                    },
                    "totalUrls": {
                      "type": "integer"
                    },
                    "completedUrls": {
                      "type": "integer"
                    },
                    "failedUrls": {
                      "type": "integer"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "completedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Batch not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/scans": {
      "get": {
        "operationId": "listBatchScans",
        "summary": "List batch scans (Growth+)",
        "description": "List the authenticated user’s batch scan history.",
        "tags": [
          "Batch"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Batch scan history returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batches": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "label": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "totalUrls": {
                            "type": "integer"
                          },
                          "completedUrls": {
                            "type": "integer"
                          },
                          "failedUrls": {
                            "type": "integer"
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/register": {
      "post": {
        "operationId": "register",
        "summary": "Register or sign in via magic link",
        "description": "Send a magic-link sign-in email. Creates an account if the email is new. No API key required. Rate limited to 3 per hour per IP.",
        "tags": [
          "Account"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              },
              "example": {
                "email": "agent@example.com"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Magic link sent (always returns 202 to prevent enumeration).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account": {
      "get": {
        "operationId": "getAccount",
        "summary": "Get account info",
        "description": "Retrieve account details, subscription status, and usage statistics.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Account info returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountInfo"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/plans": {
      "get": {
        "operationId": "listPlans",
        "summary": "List available plans",
        "description": "List Scanner tiers with pricing and limits. No authentication required. Cached for 1 hour.",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Plans listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plans": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Plan"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/subscribe": {
      "post": {
        "operationId": "subscribe",
        "summary": "Subscribe or upgrade tier",
        "description": "Create a Stripe checkout session for a paid tier, or upgrade an existing subscription.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tier"
                ],
                "properties": {
                  "tier": {
                    "type": "string",
                    "enum": [
                      "pro",
                      "growth"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout URL or upgrade confirmation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "checkoutUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expiresAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "note": {
                      "type": "string"
                    },
                    "upgraded": {
                      "type": "boolean"
                    },
                    "tier": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already on this tier or higher.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/manage": {
      "post": {
        "operationId": "manageBilling",
        "summary": "Open billing portal",
        "description": "Create a Stripe billing portal session for subscription management.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Portal URL returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "portalUrl": {
                      "type": "string",
                      "format": "uri"
                    },
                    "note": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No active subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/api-keys": {
      "get": {
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "List the user’s API keys (masked).",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Keys listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ApiKeyInfo"
                      }
                    },
                    "keyLimit": {
                      "type": "integer"
                    },
                    "keysUsed": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "Create a new API key. The full key is only returned once.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "label"
                ],
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Key created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key": {
                      "$ref": "#/components/schemas/ApiKeyInfo"
                    },
                    "fullKey": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Key limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/api-keys/{id}": {
      "delete": {
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Revoke an API key by ID. Cannot revoke the key currently in use.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "revoked": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Cannot revoke the key currently in use.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/watched-sites": {
      "get": {
        "operationId": "listWatchedSites",
        "summary": "List watched sites",
        "description": "List the user’s watched sites with latest scores.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sites listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sites": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WatchedSite"
                      }
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "used": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "addWatchedSite",
        "summary": "Add a watched site",
        "description": "Add a site to your watchlist with SSRF validation and deduplication.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "alertEnabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Site added.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSite"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or SSRF blocked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Watched sites limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Site already on watchlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/watched-sites/{id}": {
      "get": {
        "operationId": "getWatchedSite",
        "summary": "Get a watched site",
        "description": "Retrieve a watched site with score history.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Site details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSite"
                    },
                    "scoreHistory": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "score": {
                            "type": "integer"
                          },
                          "scannedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWatchedSite",
        "summary": "Update a watched site",
        "description": "Partial update. Threshold fields require Growth tier.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "alertEnabled": {
                    "type": "boolean"
                  },
                  "isCompetitor": {
                    "type": "boolean"
                  },
                  "thresholdMin": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "thresholdMax": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "thresholdNotify": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Site updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSite"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWatchedSite",
        "summary": "Remove a watched site",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Site removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/watched-sites/{id}/thresholds": {
      "get": {
        "operationId": "getThresholds",
        "summary": "Get thresholds (Growth+)",
        "description": "Retrieve threshold settings for a watched site.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Thresholds returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Thresholds"
                }
              }
            }
          },
          "403": {
            "description": "Growth tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "setThresholds",
        "summary": "Set thresholds (Growth+)",
        "description": "Set or update thresholds for a watched site. min must be less than max.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Thresholds"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Thresholds updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Thresholds"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Growth tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhooks (Pro+)",
        "description": "List the user’s webhook endpoints.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookInfo"
                      }
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "used": {
                      "type": "integer"
                    },
                    "allowedEvents": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Create a webhook (Pro+)",
        "description": "Register a webhook endpoint. Must be HTTPS. Secret returned once at creation.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "scan_complete",
                        "score_change",
                        "batch_complete",
                        "threshold_alert"
                      ]
                    }
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhook": {
                      "$ref": "#/components/schemas/WebhookInfo"
                    },
                    "secret": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Webhook limit reached or Pro tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook (Pro+)",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhook",
        "summary": "Test a webhook (Pro+)",
        "description": "Send a test delivery. Rate limited to 5 per hour.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Test result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "statusCode": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Test rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/watched-sites": {
      "get": {
        "operationId": "listWatchedSitesV2",
        "summary": "List watched sites (agent API)",
        "description": "List watched sites with thresholds. Preferred endpoint for AI agents.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sites listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sites": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WatchedSiteV2"
                      }
                    },
                    "limit": {
                      "oneOf": [
                        {
                          "type": "integer"
                        },
                        {
                          "type": "string",
                          "const": "unlimited"
                        }
                      ]
                    },
                    "used": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "addWatchedSiteV2",
        "summary": "Add a watched site (agent API)",
        "description": "Add a site to your watchlist with SSRF validation and deduplication.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "alertEnabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Site added.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSiteV2"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or SSRF blocked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Watched sites limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Site already on watchlist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/watched-sites/{id}": {
      "get": {
        "operationId": "getWatchedSiteV2",
        "summary": "Get a watched site (agent API)",
        "description": "Retrieve a watched site with thresholds and score history.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Site details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSiteV2"
                    },
                    "thresholds": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ThresholdRecord"
                      }
                    },
                    "scoreHistory": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "score": {
                            "type": "integer"
                          },
                          "scannedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateWatchedSiteV2",
        "summary": "Update a watched site (agent API)",
        "description": "Partial update of label, alertEnabled, or isCompetitor.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string"
                  },
                  "alertEnabled": {
                    "type": "boolean"
                  },
                  "isCompetitor": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Site updated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "site": {
                      "$ref": "#/components/schemas/WatchedSiteV2"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWatchedSiteV2",
        "summary": "Remove a watched site (agent API)",
        "description": "Cascades to associated thresholds.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Site removed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/watched-sites/{id}/thresholds": {
      "get": {
        "operationId": "listThresholds",
        "summary": "List thresholds (Growth+)",
        "description": "List individual threshold records for a watched site.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Thresholds listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "thresholds": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ThresholdRecord"
                      }
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Growth tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Site not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createThreshold",
        "summary": "Create a threshold (Growth+)",
        "description": "Create or update a threshold by condition type. One per condition per site.",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "condition",
                  "value"
                ],
                "properties": {
                  "condition": {
                    "type": "string",
                    "enum": [
                      "drops_below",
                      "rises_above",
                      "changes_by"
                    ]
                  },
                  "value": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Threshold created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "threshold": {
                      "$ref": "#/components/schemas/ThresholdRecord"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Growth tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/watched-sites/{id}/thresholds/{thresholdId}": {
      "delete": {
        "operationId": "deleteThreshold",
        "summary": "Delete a threshold (Growth+)",
        "tags": [
          "Watched Sites"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "thresholdId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Threshold deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Threshold not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks": {
      "get": {
        "operationId": "listWebhooksV2",
        "summary": "List webhooks (agent API, Pro+)",
        "description": "List webhook endpoints. Preferred endpoint for AI agents.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks listed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookInfo"
                      }
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "used": {
                      "type": "integer"
                    },
                    "allowedEvents": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Pro tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createWebhookV2",
        "summary": "Create a webhook (agent API, Pro+)",
        "description": "Register a webhook endpoint. Must be HTTPS. Secret returned once.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "scan_complete",
                        "score_change",
                        "batch_complete",
                        "threshold_alert"
                      ]
                    }
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhook": {
                      "$ref": "#/components/schemas/WebhookInfo"
                    },
                    "secret": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Webhook limit reached or Pro tier required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhookV2",
        "summary": "Delete a webhook (agent API, Pro+)",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "testWebhookV2",
        "summary": "Test a webhook (agent API, Pro+)",
        "description": "Send a test delivery. Rate limited to 5 per hour.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Test result.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "statusCode": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Test rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/pricing": {
      "get": {
        "operationId": "getPricing",
        "summary": "Get machine-readable pricing",
        "description": "Returns current pricing for all Zeodyn products and tiers. Cached for 1 hour. Rate limited to 100 requests per hour per IP.",
        "tags": [
          "Pricing"
        ],
        "responses": {
          "200": {
            "description": "Pricing data.",
            "headers": {
              "Cache-Control": {
                "description": "Public caching for 1 hour.",
                "schema": {
                  "type": "string",
                  "const": "public, max-age=3600"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PricingResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "description": "Seconds until the rate limit window resets.",
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Too many requests. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Check service health",
        "description": "Returns the health status of the application and its dependencies. Returns 200 when healthy, 503 when degraded.",
        "tags": [
          "Health"
        ],
        "responses": {
          "200": {
            "description": "Service is healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "healthy",
                  "timestamp": "2026-02-20T12:00:00.000Z",
                  "checks": {
                    "app": "ok",
                    "database": "ok"
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service is degraded (e.g. database unreachable).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                },
                "example": {
                  "status": "degraded",
                  "timestamp": "2026-02-20T12:00:00.000Z",
                  "checks": {
                    "app": "ok",
                    "database": "error"
                  }
                }
              }
            }
          }
        }
      },
      "head": {
        "operationId": "pingHealth",
        "summary": "Lightweight health ping",
        "description": "Returns 200 with no body. Suitable for uptime monitors.",
        "tags": [
          "Health"
        ],
        "responses": {
          "200": {
            "description": "Service is running."
          }
        }
      }
    },
    "/api/mcp/scanner": {
      "post": {
        "operationId": "mcpScannerEndpoint",
        "summary": "MCP Scanner endpoint (generic)",
        "description": "JSON-RPC 2.0 endpoint implementing the Model Context Protocol (Streamable HTTP transport). Generic endpoint for all MCP clients. Supports methods: initialize, tools/list, tools/call. 8 tools: scan_website, get_scan_results, list_scans, get_plans, get_account, list_watched_sites, add_watched_site, compare_sites. Authenticate via X-API-Key header.",
        "tags": [
          "MCP"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "tools/list",
                      "tools/call"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/list"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "oneOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "type": "object"
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded."
          }
        }
      }
    },
    "/api/mcp/claude/scanner": {
      "post": {
        "operationId": "mcpClaudeScannerEndpoint",
        "summary": "MCP Scanner endpoint (Claude-optimised)",
        "description": "JSON-RPC 2.0 endpoint implementing the Model Context Protocol, optimised for Claude clients. Same 8 tools as the generic /api/mcp/scanner endpoint. Authenticate via X-API-Key header.",
        "tags": [
          "MCP"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "initialize",
                      "tools/list",
                      "tools/call"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tools/call",
                "params": {
                  "name": "scan_website",
                  "arguments": {
                    "url": "https://example.com"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "oneOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "type": "object"
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded."
          }
        }
      }
    },
    "/api/mcp/health": {
      "get": {
        "operationId": "mcpHealth",
        "summary": "MCP health check",
        "description": "Returns the health status of the MCP server. Returns 200 when healthy, 503 when degraded.",
        "tags": [
          "MCP"
        ],
        "responses": {
          "200": {
            "description": "MCP server is healthy.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "healthy",
                        "degraded"
                      ]
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "status": "healthy",
                  "timestamp": "2026-03-19T12:00:00.000Z"
                }
              }
            }
          },
          "503": {
            "description": "MCP server is degraded.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "const": "degraded"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/a2a": {
      "post": {
        "operationId": "a2aEndpoint",
        "summary": "Agent-to-Agent (A2A) protocol endpoint",
        "description": "JSON-RPC 2.0 endpoint implementing Google’s Agent-to-Agent protocol. Supports methods: tasks/send, tasks/get, tasks/cancel. Accepts natural language messages and routes to appropriate Zeodyn™ capabilities. Authenticate via X-API-Key header.",
        "tags": [
          "A2A"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "jsonrpc",
                  "method"
                ],
                "properties": {
                  "jsonrpc": {
                    "type": "string",
                    "const": "2.0"
                  },
                  "id": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ]
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "tasks/send",
                      "tasks/get",
                      "tasks/cancel"
                    ]
                  },
                  "params": {
                    "type": "object"
                  }
                }
              },
              "example": {
                "jsonrpc": "2.0",
                "id": 1,
                "method": "tasks/send",
                "params": {
                  "id": "task-001",
                  "message": {
                    "role": "user",
                    "parts": [
                      {
                        "type": "text",
                        "text": "Scan https://example.com for agent commerce readiness"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC 2.0 response containing the task object.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jsonrpc": {
                      "type": "string",
                      "const": "2.0"
                    },
                    "id": {
                      "oneOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "integer"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "object",
                          "properties": {
                            "state": {
                              "type": "string",
                              "enum": [
                                "submitted",
                                "working",
                                "completed",
                                "failed",
                                "canceled"
                              ]
                            }
                          }
                        },
                        "artifacts": {
                          "type": "array"
                        },
                        "history": {
                          "type": "array"
                        }
                      }
                    },
                    "error": {
                      "type": "object",
                      "properties": {
                        "code": {
                          "type": "integer"
                        },
                        "message": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded."
          }
        }
      }
    },
    "/api/acp/checkouts": {
      "post": {
        "operationId": "acpCreateCheckout",
        "summary": "Create an ACP checkout session",
        "description": "Create a new Agentic Commerce Protocol checkout session. Specify items from the ACP product catalogue. Returns the checkout state with line items, totals, fulfilment options, and payment provider details.",
        "tags": [
          "ACP"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcpCreateCheckoutRequest"
              },
              "example": {
                "items": [
                  {
                    "id": "scanner_pro",
                    "quantity": 1
                  }
                ],
                "buyer": {
                  "first_name": "Example",
                  "last_name": "Agent",
                  "email": "agent@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Checkout session created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpCheckout"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — unknown product ID, invalid quantity, or malformed body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded or too many open checkout sessions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          }
        }
      }
    },
    "/api/acp/checkouts/{id}": {
      "get": {
        "operationId": "acpGetCheckout",
        "summary": "Retrieve an ACP checkout session",
        "description": "Retrieve an existing ACP checkout session by its ID.",
        "tags": [
          "ACP"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ACP checkout session ID (acp_cs_ prefix).",
            "schema": {
              "type": "string",
              "pattern": "^acp_cs_[a-f0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Checkout session returned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpCheckout"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "404": {
            "description": "Checkout session not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "acpUpdateCheckout",
        "summary": "Update an ACP checkout session",
        "description": "Update an existing checkout session. Can change items or buyer information before payment. Only allowed when the checkout status is not_ready_for_payment or ready_for_payment.",
        "tags": [
          "ACP"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ACP checkout session ID (acp_cs_ prefix).",
            "schema": {
              "type": "string",
              "pattern": "^acp_cs_[a-f0-9]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcpUpdateCheckoutRequest"
              },
              "example": {
                "items": [
                  {
                    "id": "scanner_growth",
                    "quantity": 1
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout session updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpCheckout"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — unknown product ID, invalid quantity, or malformed body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "404": {
            "description": "Checkout session not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "409": {
            "description": "Checkout is in_progress, completed, or canceled and cannot be updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          }
        }
      }
    },
    "/api/acp/checkouts/{id}/complete": {
      "post": {
        "operationId": "acpCompleteCheckout",
        "summary": "Complete an ACP checkout with payment",
        "description": "Complete a checkout session by providing a Stripe SharedPaymentToken. Processes payment, creates a subscription, and provisions access. Returns the completed checkout with order details. Digital fulfilment is instant.",
        "tags": [
          "ACP"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ACP checkout session ID (acp_cs_ prefix).",
            "schema": {
              "type": "string",
              "pattern": "^acp_cs_[a-f0-9]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcpCompleteCheckoutRequest"
              },
              "example": {
                "shared_payment_token": "spt_1abc2def3ghi"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout completed. Payment processed, subscription created, access provisioned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpCompletedCheckout"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — missing payment token or invalid checkout state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "402": {
            "description": "Payment failed — the SharedPaymentToken may be invalid, expired, or declined.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "404": {
            "description": "Checkout session not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "409": {
            "description": "Checkout is already completed, canceled, or currently being processed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          }
        }
      }
    },
    "/api/acp/checkouts/{id}/cancel": {
      "post": {
        "operationId": "acpCancelCheckout",
        "summary": "Cancel an ACP checkout session",
        "description": "Cancel a checkout session. Only allowed when the session is not yet completed.",
        "tags": [
          "ACP"
        ],
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "ACP checkout session ID (acp_cs_ prefix).",
            "schema": {
              "type": "string",
              "pattern": "^acp_cs_[a-f0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Checkout session canceled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpCheckout"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "404": {
            "description": "Checkout session not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "409": {
            "description": "Checkout is already completed or canceled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcpError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key with zd_live_ prefix. Create keys at https://zeodyn.com/account/api-keys"
      }
    },
    "schemas": {
      "ScanRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "description": "URL to scan. If no scheme is provided, `https://` is prepended automatically.",
            "examples": [
              "https://example.com",
              "example.com"
            ]
          }
        }
      },
      "ScanResult": {
        "type": "object",
        "description": "Complete scan result with Zeodyn Score™ and dimension breakdowns.",
        "required": [
          "id",
          "score",
          "band",
          "bandLabel",
          "bandSummary",
          "methodology",
          "scannedUrl",
          "scannedAt",
          "failGatesTriggered",
          "dimensions",
          "summary"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique identifier for this scan result. Use with `GET /api/results/{id}` to retrieve later."
          },
          "score": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Zeodyn Score™ composite (weighted geometric mean of dimension scores)."
          },
          "band": {
            "$ref": "#/components/schemas/ScoreBand"
          },
          "bandLabel": {
            "type": "string",
            "description": "Human-readable band name.",
            "examples": [
              "Agent-Ready",
              "Strong",
              "Developing",
              "Limited",
              "Not Ready"
            ]
          },
          "bandSummary": {
            "type": "string",
            "description": "Dynamic one-line summary explaining the score."
          },
          "methodology": {
            "type": "string",
            "const": "Agent Commerce Stack™ v1.0",
            "description": "Scoring methodology identifier."
          },
          "scannedUrl": {
            "type": "string",
            "format": "uri",
            "description": "The normalised URL that was scanned."
          },
          "scannedAt": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of when the scan was performed."
          },
          "failGatesTriggered": {
            "type": "integer",
            "minimum": 0,
            "maximum": 6,
            "description": "Number of dimensions where a fail gate capped the score."
          },
          "dimensions": {
            "type": "array",
            "minItems": 6,
            "maxItems": 6,
            "items": {
              "$ref": "#/components/schemas/DimensionScore"
            },
            "description": "Scores for all six dimensions: Discovery & Access, Structured Data, Commerce Data, Protocol Support, Security & Trust, Technical Performance."
          },
          "summary": {
            "$ref": "#/components/schemas/ResultSummary"
          },
          "pagesScanned": {
            "type": "integer",
            "minimum": 1,
            "description": "Number of pages analysed. 1 for free tier, 2 for Pro, up to 5 for Growth."
          },
          "scanTier": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "growth"
            ],
            "description": "The scanning tier used for this scan."
          },
          "pages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PageScore"
            },
            "description": "Per-page dimension scores. Present when pagesScanned > 1 (Pro and Growth tiers)."
          }
        }
      },
      "PageScore": {
        "type": "object",
        "description": "Per-page dimension scores for multi-page scans.",
        "required": [
          "url",
          "type",
          "dimensions"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "The URL of this page."
          },
          "type": {
            "type": "string",
            "enum": [
              "homepage",
              "product"
            ],
            "description": "Page classification."
          },
          "dimensions": {
            "type": "object",
            "description": "Dimension scores for this page.",
            "properties": {
              "discoveryAccess": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "structuredData": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "commerceData": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "protocolSupport": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "securityTrust": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              },
              "technicalPerformance": {
                "type": "integer",
                "minimum": 1,
                "maximum": 100
              }
            }
          }
        }
      },
      "ScoreBand": {
        "type": "string",
        "enum": [
          "agent-ready",
          "strong-foundation",
          "developing",
          "limited",
          "not-ready"
        ],
        "description": "Score band: agent-ready (90–100), strong-foundation (70–89), developing (50–69), limited (25–49), not-ready (1–24)."
      },
      "DimensionScore": {
        "type": "object",
        "required": [
          "id",
          "name",
          "question",
          "score",
          "weightLabel",
          "subChecks",
          "failGate",
          "recommendations"
        ],
        "properties": {
          "id": {
            "type": "string",
            "enum": [
              "discovery-access",
              "structured-data",
              "commerce-data",
              "protocol-support",
              "security-trust",
              "technical-performance"
            ],
            "description": "Machine-readable dimension identifier."
          },
          "name": {
            "type": "string",
            "description": "Human-readable dimension name.",
            "examples": [
              "Discovery & Access",
              "Structured Data",
              "Commerce Data",
              "Protocol Support",
              "Security & Trust",
              "Technical Performance"
            ]
          },
          "question": {
            "type": "string",
            "description": "The question this dimension answers."
          },
          "score": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Dimension score after fail gate application."
          },
          "weightLabel": {
            "type": "string",
            "enum": [
              "Very high",
              "High",
              "Moderate"
            ],
            "description": "Qualitative weight label. Exact numeric weights are proprietary."
          },
          "subChecks": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SubCheck"
            },
            "description": "Individual checks within this dimension."
          },
          "failGate": {
            "$ref": "#/components/schemas/FailGate"
          },
          "recommendations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Recommendation"
            },
            "description": "Actionable recommendations for this dimension."
          }
        }
      },
      "SubCheck": {
        "type": "object",
        "required": [
          "id",
          "name",
          "score",
          "passed",
          "details"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Machine-readable sub-check identifier."
          },
          "name": {
            "type": "string",
            "description": "Human-readable sub-check name."
          },
          "score": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Sub-check score."
          },
          "passed": {
            "type": "boolean",
            "description": "Whether this check passed (score ≥ 60)."
          },
          "details": {
            "type": "string",
            "description": "Human-readable explanation of what was found."
          }
        }
      },
      "FailGate": {
        "type": "object",
        "required": [
          "triggered",
          "reason"
        ],
        "properties": {
          "triggered": {
            "type": "boolean",
            "description": "Whether this dimension’s fail gate was triggered."
          },
          "reason": {
            "type": "string",
            "description": "Explanation of why the fail gate was triggered (empty if not triggered)."
          }
        }
      },
      "Recommendation": {
        "type": "object",
        "required": [
          "priority",
          "title",
          "description",
          "scoreImpact"
        ],
        "properties": {
          "priority": {
            "type": "string",
            "enum": [
              "high",
              "medium",
              "low"
            ],
            "description": "Implementation priority."
          },
          "title": {
            "type": "string",
            "description": "Short recommendation title."
          },
          "description": {
            "type": "string",
            "description": "Detailed explanation and guidance."
          },
          "scoreImpact": {
            "type": "string",
            "enum": [
              "major",
              "moderate",
              "minor"
            ],
            "description": "Expected impact on the Zeodyn Score if implemented."
          }
        }
      },
      "ResultSummary": {
        "type": "object",
        "required": [
          "totalRecommendations",
          "highPriority",
          "mediumPriority",
          "lowPriority",
          "topDimension",
          "bottomDimension"
        ],
        "properties": {
          "totalRecommendations": {
            "type": "integer",
            "minimum": 0,
            "description": "Total number of recommendations across all dimensions."
          },
          "highPriority": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of high-priority recommendations."
          },
          "mediumPriority": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of medium-priority recommendations."
          },
          "lowPriority": {
            "type": "integer",
            "minimum": 0,
            "description": "Number of low-priority recommendations."
          },
          "topDimension": {
            "type": "string",
            "description": "Name of the highest-scoring dimension."
          },
          "bottomDimension": {
            "type": "string",
            "description": "Name of the lowest-scoring dimension."
          }
        }
      },
      "PricingResponse": {
        "type": "object",
        "required": [
          "provider",
          "legalEntity",
          "website",
          "currency",
          "lastUpdated",
          "products"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "const": "Zeodyn™"
          },
          "legalEntity": {
            "type": "string",
            "const": "Virtual Factory Solutions Ltd."
          },
          "website": {
            "type": "string",
            "format": "uri"
          },
          "currency": {
            "type": "string",
            "const": "GBP",
            "description": "All prices are in British Pounds (GBP)."
          },
          "lastUpdated": {
            "type": "string",
            "format": "date",
            "description": "Date the pricing was last updated."
          },
          "products": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PricingProduct"
            }
          }
        }
      },
      "PricingProduct": {
        "type": "object",
        "required": [
          "name",
          "slug",
          "url",
          "status"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Product name."
          },
          "slug": {
            "type": "string",
            "description": "URL-safe product identifier."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Product page URL."
          },
          "status": {
            "type": "string",
            "enum": [
              "live",
              "coming_soon"
            ],
            "description": "Product availability status."
          },
          "methodology": {
            "type": "string",
            "description": "Scoring methodology (for scanner products)."
          },
          "tiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PricingTier"
            },
            "description": "Available pricing tiers (only present for live products)."
          }
        }
      },
      "PricingTier": {
        "type": "object",
        "required": [
          "name",
          "price",
          "period",
          "features"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Tier name.",
            "examples": [
              "Free",
              "Pro",
              "Growth",
              "Enterprise"
            ]
          },
          "price": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "description": "Monthly price in GBP. Null for custom/enterprise pricing."
          },
          "period": {
            "type": "string",
            "enum": [
              "month",
              "custom"
            ],
            "description": "Billing period."
          },
          "contact": {
            "type": "string",
            "format": "email",
            "description": "Contact email for custom-priced tiers."
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of features included in this tier."
          }
        }
      },
      "HealthResponse": {
        "type": "object",
        "required": [
          "status",
          "timestamp",
          "checks"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "degraded"
            ],
            "description": "Overall service status."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp."
          },
          "checks": {
            "type": "object",
            "required": [
              "app",
              "database"
            ],
            "properties": {
              "app": {
                "type": "string",
                "const": "ok",
                "description": "Application status (always ok if the endpoint responds)."
              },
              "database": {
                "type": "string",
                "enum": [
                  "ok",
                  "error",
                  "unknown"
                ],
                "description": "Database connectivity status. \"unknown\" when the database connection string is not configured."
              }
            }
          }
        }
      },
      "AccountInfo": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "tier": {
            "type": "string"
          },
          "subscription": {
            "type": "object",
            "properties": {
              "isActive": {
                "type": "boolean"
              },
              "isPaid": {
                "type": "boolean"
              },
              "isCanceling": {
                "type": "boolean"
              },
              "currentPeriodEnd": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "usage": {
            "type": "object",
            "properties": {
              "dailyScans": {
                "type": "integer"
              },
              "dailyScanLimit": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "monthlyApiCalls": {
                "type": "integer"
              },
              "monthlyApiCallLimit": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              }
            }
          },
          "counts": {
            "type": "object",
            "properties": {
              "watchedSites": {
                "type": "integer"
              },
              "watchedSitesLimit": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "apiKeys": {
                "type": "integer"
              },
              "apiKeysLimit": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "webhooks": {
                "type": "integer"
              },
              "webhooksLimit": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              }
            }
          }
        }
      },
      "Plan": {
        "type": "object",
        "properties": {
          "tier": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "price": {
            "type": "string",
            "description": "Human-readable price, e.g. \"Free\", \"£19/month\". All prices exclude VAT."
          },
          "taxIncluded": {
            "type": "boolean",
            "description": "Whether VAT is included in the price. Always false."
          },
          "priceCurrency": {
            "type": "string",
            "description": "ISO 4217 currency code. Always GBP."
          },
          "priceMonthlyGbp": {
            "type": [
              "number",
              "null"
            ]
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "limits": {
            "type": "object",
            "properties": {
              "scansPerDay": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "watchedSites": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "apiCallsMonthly": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "apiKeysMax": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              },
              "webhooksMax": {
                "oneOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string",
                    "const": "unlimited"
                  }
                ]
              }
            }
          }
        }
      },
      "ApiKeyInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "keyPrefix": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "isActive": {
            "type": "boolean"
          }
        }
      },
      "WatchedSite": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastScore": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastScannedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "alertEnabled": {
            "type": "boolean"
          },
          "scoreChange": {
            "type": [
              "integer",
              "null"
            ]
          },
          "isCompetitor": {
            "type": "boolean"
          },
          "thresholdMin": {
            "type": [
              "integer",
              "null"
            ]
          },
          "thresholdMax": {
            "type": [
              "integer",
              "null"
            ]
          },
          "thresholdNotify": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Thresholds": {
        "type": "object",
        "required": [
          "min",
          "max",
          "notify"
        ],
        "properties": {
          "min": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "max": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 100
          },
          "notify": {
            "type": "boolean"
          }
        }
      },
      "WatchedSiteV2": {
        "type": "object",
        "description": "Watched site with inline thresholds (agent API).",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "lastScore": {
            "type": [
              "integer",
              "null"
            ]
          },
          "lastScannedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "alertEnabled": {
            "type": "boolean"
          },
          "scoreChange": {
            "type": [
              "integer",
              "null"
            ]
          },
          "isCompetitor": {
            "type": "boolean"
          },
          "thresholds": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ThresholdRecord"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ThresholdRecord": {
        "type": "object",
        "description": "Individual score threshold with a condition type.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "condition": {
            "type": "string",
            "enum": [
              "drops_below",
              "rises_above",
              "changes_by"
            ]
          },
          "value": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "isActive": {
            "type": "boolean"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string"
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "isActive": {
            "type": "boolean"
          },
          "lastTriggeredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "lastStatusCode": {
            "type": [
              "integer",
              "null"
            ]
          },
          "failureCount": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message."
          }
        }
      },
      "RateLimitError": {
        "type": "object",
        "required": [
          "error",
          "message",
          "retryAfter",
          "upgradeUrl"
        ],
        "properties": {
          "error": {
            "type": "string",
            "const": "scan_limit_reached"
          },
          "message": {
            "type": "string",
            "description": "Human-readable rate limit message."
          },
          "retryAfter": {
            "type": "integer",
            "description": "Seconds until the rate limit window resets."
          },
          "upgradeUrl": {
            "type": "string",
            "description": "URL to the pricing page for higher limits."
          }
        }
      },
      "AcpCreateCheckoutRequest": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1,
            "items": {
              "$ref": "#/components/schemas/AcpLineItemRequest"
            },
            "description": "Products to include in the checkout (currently limited to 1 item)."
          },
          "buyer": {
            "$ref": "#/components/schemas/AcpBuyer"
          },
          "idempotency_key": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^[a-zA-Z0-9_\\-]+$",
            "description": "Optional idempotency key to prevent duplicate checkout creation."
          }
        }
      },
      "AcpUpdateCheckoutRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1,
            "items": {
              "$ref": "#/components/schemas/AcpLineItemRequest"
            },
            "description": "Updated product selection (currently limited to 1 item)."
          },
          "buyer": {
            "$ref": "#/components/schemas/AcpBuyer"
          },
          "fulfillment_option_id": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^[a-zA-Z0-9_]+$",
            "description": "Selected fulfilment option ID.",
            "examples": [
              "instant_access"
            ]
          }
        }
      },
      "AcpCompleteCheckoutRequest": {
        "type": "object",
        "required": [
          "shared_payment_token"
        ],
        "properties": {
          "shared_payment_token": {
            "type": "string",
            "maxLength": 255,
            "pattern": "^spt_[a-zA-Z0-9_]+$",
            "description": "Stripe SharedPaymentToken provided by the agent for payment processing."
          },
          "idempotency_key": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^[a-zA-Z0-9_\\-]+$",
            "description": "Optional idempotency key to prevent duplicate payment processing."
          }
        }
      },
      "AcpLineItemRequest": {
        "type": "object",
        "required": [
          "id",
          "quantity"
        ],
        "properties": {
          "id": {
            "type": "string",
            "maxLength": 64,
            "pattern": "^[a-zA-Z0-9_]+$",
            "description": "Product ID from the ACP catalogue.",
            "examples": [
              "scanner_pro",
              "scanner_growth"
            ]
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1,
            "description": "Quantity to purchase (currently limited to 1)."
          }
        }
      },
      "AcpBuyer": {
        "type": "object",
        "description": "Buyer information. When provided, first_name, last_name, and email are required.",
        "required": [
          "first_name",
          "last_name",
          "email"
        ],
        "properties": {
          "first_name": {
            "type": "string",
            "maxLength": 100,
            "description": "Buyer first name."
          },
          "last_name": {
            "type": "string",
            "maxLength": 100,
            "description": "Buyer last name."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 320,
            "description": "Buyer email address."
          },
          "phone_number": {
            "type": "string",
            "maxLength": 20,
            "description": "Buyer phone number."
          }
        }
      },
      "AcpCheckout": {
        "type": "object",
        "description": "ACP checkout session state.",
        "required": [
          "id",
          "status",
          "currency",
          "line_items",
          "fulfillment_options",
          "fulfillment_option_id",
          "payment_provider",
          "totals",
          "messages",
          "links"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "ACP checkout session ID.",
            "examples": [
              "acp_cs_a1b2c3d4e5f6"
            ]
          },
          "status": {
            "$ref": "#/components/schemas/AcpCheckoutStatus"
          },
          "currency": {
            "type": "string",
            "const": "gbp",
            "description": "Currency code."
          },
          "line_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpLineItem"
            },
            "description": "Products in the checkout."
          },
          "fulfillment_options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpFulfillmentOption"
            },
            "description": "Available fulfilment methods."
          },
          "fulfillment_option_id": {
            "type": "string",
            "description": "Selected fulfilment option ID."
          },
          "payment_provider": {
            "$ref": "#/components/schemas/AcpPaymentProvider"
          },
          "totals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpTotal"
            },
            "description": "Order totals."
          },
          "buyer": {
            "$ref": "#/components/schemas/AcpBuyer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpMessage"
            },
            "description": "Informational messages for the agent."
          },
          "links": {
            "type": "object",
            "description": "Related links.",
            "properties": {
              "terms_of_use": {
                "type": "string",
                "format": "uri"
              },
              "privacy_policy": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "order": {
            "$ref": "#/components/schemas/AcpOrder"
          }
        }
      },
      "AcpCompletedCheckout": {
        "type": "object",
        "description": "Completed ACP checkout with order details.",
        "required": [
          "id",
          "status",
          "currency",
          "line_items",
          "totals",
          "order",
          "links"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "ACP checkout session ID."
          },
          "status": {
            "type": "string",
            "const": "completed"
          },
          "currency": {
            "type": "string",
            "const": "gbp"
          },
          "line_items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpLineItem"
            }
          },
          "fulfillment_options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpFulfillmentOption"
            }
          },
          "fulfillment_option_id": {
            "type": "string"
          },
          "payment_provider": {
            "$ref": "#/components/schemas/AcpPaymentProvider"
          },
          "totals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpTotal"
            }
          },
          "buyer": {
            "$ref": "#/components/schemas/AcpBuyer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AcpMessage"
            }
          },
          "links": {
            "type": "object",
            "properties": {
              "terms_of_use": {
                "type": "string",
                "format": "uri"
              },
              "privacy_policy": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          "order": {
            "$ref": "#/components/schemas/AcpOrder"
          }
        }
      },
      "AcpCheckoutStatus": {
        "type": "string",
        "enum": [
          "not_ready_for_payment",
          "ready_for_payment",
          "in_progress",
          "completed",
          "canceled"
        ],
        "description": "Checkout lifecycle status. not_ready_for_payment: missing required info. ready_for_payment: can accept payment. in_progress: payment being processed. completed: payment successful, access provisioned. canceled: session canceled."
      },
      "AcpLineItem": {
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "quantity",
          "base_amount",
          "discount",
          "subtotal",
          "tax",
          "total"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Product ID."
          },
          "name": {
            "type": "string",
            "description": "Product display name."
          },
          "description": {
            "type": "string",
            "description": "Product description."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1
          },
          "base_amount": {
            "type": "integer",
            "description": "Price per unit in minor currency units (pence)."
          },
          "discount": {
            "type": "integer",
            "description": "Discount amount in minor currency units."
          },
          "subtotal": {
            "type": "integer",
            "description": "Line subtotal in minor currency units."
          },
          "tax": {
            "type": "integer",
            "description": "Tax amount in minor currency units."
          },
          "total": {
            "type": "integer",
            "description": "Line total in minor currency units."
          }
        }
      },
      "AcpTotal": {
        "type": "object",
        "required": [
          "label",
          "amount"
        ],
        "properties": {
          "label": {
            "type": "string",
            "description": "Total label.",
            "examples": [
              "Subtotal",
              "Total"
            ]
          },
          "amount": {
            "type": "integer",
            "description": "Amount in minor currency units (pence)."
          }
        }
      },
      "AcpFulfillmentOption": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "digital",
            "description": "Fulfilment type."
          },
          "id": {
            "type": "string",
            "description": "Fulfilment option ID."
          },
          "title": {
            "type": "string",
            "description": "Fulfilment option title."
          },
          "subtitle": {
            "type": "string",
            "description": "Fulfilment option description."
          },
          "subtotal": {
            "type": "integer",
            "description": "Subtotal for fulfilment in minor currency units."
          },
          "tax": {
            "type": "integer",
            "description": "Tax for fulfilment in minor currency units."
          },
          "total": {
            "type": "integer",
            "description": "Total for fulfilment in minor currency units."
          }
        }
      },
      "AcpPaymentProvider": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "const": "stripe",
            "description": "Payment provider."
          },
          "supported_payment_methods": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Supported payment method types.",
            "examples": [
              [
                "card"
              ]
            ]
          }
        }
      },
      "AcpOrder": {
        "type": "object",
        "description": "Order details returned after successful payment and provisioning.",
        "required": [
          "id",
          "status",
          "permalink",
          "messages"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Order identifier (ord_ prefix).",
            "examples": [
              "ord_a1b2c3d4e5f6"
            ]
          },
          "status": {
            "type": "string",
            "description": "Order status.",
            "examples": [
              "active"
            ]
          },
          "permalink": {
            "type": "string",
            "format": "uri",
            "description": "URL to the account dashboard."
          },
          "messages": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Fulfilment messages confirming provisioning."
          }
        }
      },
      "AcpError": {
        "type": "object",
        "description": "ACP error response.",
        "required": [
          "type",
          "code",
          "message"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Error category.",
            "examples": [
              "invalid_request",
              "unauthorized",
              "not_found",
              "conflict",
              "payment_failed",
              "rate_limited"
            ]
          },
          "code": {
            "type": "string",
            "description": "Machine-readable error code.",
            "examples": [
              "validation_error",
              "invalid_token",
              "checkout_not_found",
              "checkout_not_modifiable",
              "payment_error"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable error description."
          }
        }
      },
      "AcpMessage": {
        "type": "object",
        "description": "Informational message included in checkout responses.",
        "required": [
          "type",
          "content_type",
          "content"
        ],
        "properties": {
          "type": {
            "type": "string",
            "description": "Message type.",
            "examples": [
              "info"
            ]
          },
          "content_type": {
            "type": "string",
            "description": "Content MIME type.",
            "examples": [
              "plain"
            ]
          },
          "content": {
            "type": "string",
            "description": "Message text."
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Scanner",
      "description": "Scan URLs for AI agent commerce readiness and retrieve results."
    },
    {
      "name": "Pricing",
      "description": "Machine-readable pricing for all Zeodyn products."
    },
    {
      "name": "Batch",
      "description": "Batch scanning for Growth tier and above. Submit multiple URLs in a single request."
    },
    {
      "name": "Account",
      "description": "Account management, subscription, billing, and API key operations."
    },
    {
      "name": "Watched Sites",
      "description": "Manage watched sites, score history, and thresholds."
    },
    {
      "name": "Webhooks",
      "description": "Create, manage, and test webhook endpoints."
    },
    {
      "name": "Health",
      "description": "Service health and uptime monitoring."
    },
    {
      "name": "MCP",
      "description": "Model Context Protocol (MCP) server. JSON-RPC 2.0 over POST /api/mcp/scanner (generic) and POST /api/mcp/claude/scanner (Claude-optimised). Streamable HTTP transport with 8 tools for agent integration. Health check at GET /api/mcp/health."
    },
    {
      "name": "A2A",
      "description": "Agent-to-Agent (A2A) protocol endpoint. JSON-RPC 2.0 over POST /api/a2a. Task-based interaction with natural language intent detection."
    },
    {
      "name": "ACP",
      "description": "Agentic Commerce Protocol (ACP) checkout endpoints. Create, retrieve, update, complete, and cancel checkout sessions for AI agent-driven purchases. Manifest at /.well-known/acp/config.json."
    }
  ]
}