{
  "openapi": "3.1.0",
  "info": {
    "title": "AlterLab API",
    "summary": "Production-grade web scraping, crawling, and data extraction API.",
    "description": "AlterLab is a Data-as-a-Service platform that provides intelligent web scraping with automatic anti-bot bypass, proxy rotation, and structured data extraction.\n\n## Authentication\n\nAll API requests require an API key passed via the `X-API-Key` header:\n\n```\nX-API-Key: sk_live_your_key_here\n```\n\nGet your API key from the [AlterLab Dashboard](https://alterlab.io/dashboard/api-keys).\n\n## Rate Limits\n\nRate limits depend on your plan tier. Exceeding them returns `429 Too Many Requests`.\n\n## Credits\n\nEach request costs credits based on the scraping tier used. Check your balance via the `/api/v1/usage/balance` endpoint.",
    "contact": {
      "name": "AlterLab Support",
      "url": "https://alterlab.io/",
      "email": "support@alterlab.io"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://alterlab.io/terms"
    },
    "version": "1.0.0",
    "x-llm-instructions": "AlterLab is a web scraping API. Use POST /api/v1/scrape for single URLs (sync=true returns results immediately). Use POST /api/v1/batch for up to 100 URLs. Use POST /api/v1/crawl for full-site discovery. Use POST /api/v1/schedules for recurring scrapes. Use POST /api/v1/monitors to watch URLs for changes. All requests require X-API-Key header. Check balance with GET /api/v1/billing/balance before large operations. For async scrape (sync=false), poll GET /api/v1/jobs/{job_id} until status is 'succeeded', 'failed', or 'rejected'. A 'rejected' status means the job was not processed due to insufficient balance (HTTP 402) — stop polling and check your balance. Tier escalation is automatic — start with mode='auto' unless you need JS rendering specifically."
  },
  "servers": [
    {
      "url": "https://api.alterlab.io",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/v1/health/extraction": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Extraction Health Check",
        "description": "LLM extraction readiness endpoint.\n\nReports whether extraction is configured and ready to accept requests.\nRequires authentication (X-API-Key or Bearer JWT).\n\nTo enable extraction locally:\n  1. Set ENABLE_LLM_EXTRACTION=true in .env\n  2. Set WORKER_LLM_API_KEY to your OpenRouter or OpenAI key\n  3. Restart services: docker compose up -d api worker",
        "operationId": "extraction_health_check_api_v1_health_extraction_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionHealthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Health Check V1",
        "description": "Versioned health check endpoint (alias for /health).\n\nReturns only {status: ok|unavailable} — no infrastructure details.",
        "operationId": "health_check_v1_api_v1_health_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MinimalHealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health-check": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Health Check External",
        "description": "External health check endpoint for Traefik health-router.\n\nTraefik routes alterlab.io/health-check to this endpoint.\nSame behavior as /health — checks DB and Redis, returns 503 if unhealthy.\nReturns only {status: ok|unavailable} — no infrastructure details.",
        "operationId": "health_check_external_health_check_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MinimalHealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/ocr": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Ocr Health Check",
        "description": "OCR readiness endpoint: availability, versions, and languages.\n\nRequires admin authentication. Exposes Tesseract/Pillow version strings\nwhich could be used to target known CVEs — restrict to admin access only.",
        "operationId": "ocr_health_check_api_v1_health_ocr_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OCRHealthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/health/ready": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Readiness Check",
        "description": "Kubernetes-style readiness probe.\n\nReturns 200 if the service is ready to accept traffic,\n503 otherwise. Checks database and redis connectivity.\nReturns only {ready: true|false} — no infrastructure details in body.",
        "operationId": "readiness_check_api_v1_health_ready_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/health/live": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Liveness Check",
        "description": "Kubernetes-style liveness probe.\n\nReturns 200 if the process is alive. Does not check external\ndependencies. Use /ready for full readiness check.",
        "operationId": "liveness_check_api_v1_health_live_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/health/jobs": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Job Health Check",
        "description": "Job queue health check endpoint.\n\nRate limited: 10 requests per minute per IP.\n\nReturns information about job queue health:\n- stuck_jobs: Number of jobs stuck longer than timeout threshold\n- threshold: Maximum allowed stuck jobs before alert (5)\n- status: \"healthy\" or \"degraded\"\n- queue_depth: Current number of jobs waiting to be processed\n- message: Human-readable status message\n\nUse this to monitor job processing health and detect\njobs that are stuck due to worker issues or desync.",
        "operationId": "job_health_check_api_v1_health_jobs_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/status": {
      "get": {
        "tags": [
          "Health"
        ],
        "summary": "Public Status",
        "description": "Public status endpoint for the status page.\n\nReturns simplified status for each service without exposing\ninternal details. Suitable for public consumption.\n\nServices checked:\n- API: FastAPI application health\n- Database: PostgreSQL connectivity\n- Cache: Redis connectivity\n- Worker: Background job processor (via Redis queue check)",
        "operationId": "public_status_api_v1_status_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicStatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/me": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Get Current User",
        "description": "Get current user with balance-based tier and credit information.",
        "operationId": "get_current_user_api_v1_auth_me_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/welcome-status": {
      "get": {
        "tags": [
          "Auth"
        ],
        "summary": "Get Welcome Status",
        "description": "Get welcome bonus status for users with reduced bonus.\n\nReturns sibling accounts (obfuscated), payment status, and unlock eligibility.\nOnly returns meaningful data for users with metadata.reduced_bonus = true.",
        "operationId": "get_welcome_status_api_v1_auth_welcome_status_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WelcomeStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/unlock-welcome-bonus": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Unlock Welcome Bonus",
        "description": "Unlock the remaining welcome bonus after a user has made a deposit.\n\nChecks that the user has reduced_bonus metadata and has made at least one deposit.\nGrants the remaining bonus (full - reduced) with an idempotency key.",
        "operationId": "unlock_welcome_bonus_api_v1_auth_unlock_welcome_bonus_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/check-email": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Check Email",
        "description": "Check if an email exists and if it has a password set.\n\nSECURITY: Rate limited per-IP (5/min) and per-email (10/hour) to prevent\nemail enumeration attacks via distributed IPs.",
        "operationId": "check_email_api_v1_auth_check_email_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EmailCheckRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EmailCheckResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/initiate-signup": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Initiate Signup",
        "description": "Initiate signup - stores pending signup in Redis and sends OTP.\n\nThe user's credentials are NOT saved to the database until they verify\ntheir email via the /complete-signup endpoint.",
        "operationId": "initiate_signup_api_v1_auth_initiate_signup_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiateSignUpRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitiateSignUpResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/complete-signup": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Complete Signup",
        "description": "Complete signup by verifying OTP and creating the user account.\n\nThis endpoint must be called after /initiate-signup to finalize\naccount creation.",
        "operationId": "complete_signup_api_v1_auth_complete_signup_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteSignUpRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/signup": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Signup",
        "description": "Legacy signup endpoint — deprecated.\n\nThis endpoint previously created accounts without OTP email verification,\nbypassing fraud prevention controls. Use the OTP-verified flow instead:\nPOST /api/v1/auth/initiate-signup → POST /api/v1/auth/complete-signup\n\nSee: https://github.com/RapierCraft/AlterLab/issues/533",
        "operationId": "signup_api_v1_auth_signup_post",
        "responses": {
          "410": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Login",
        "description": "Login with email and password.\n\nSECURITY: Rate limited per-IP (middleware, 5/15min) AND per-email (in-endpoint,\n5/15min + progressive lockout at 10/hour) to prevent distributed brute-force.",
        "operationId": "login_api_v1_auth_login_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/send-verification-code": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Send Verification Code",
        "description": "Send verification code to user's email.\n\nSECURITY: Rate limited per-IP (5/min) and per-email (3/hour) to prevent\ninbox flooding and email enumeration attacks.",
        "operationId": "send_verification_code_api_v1_auth_send_verification_code_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendVerificationCodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/verify-code": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Verify Code",
        "description": "Verify email with code and award welcome credits.",
        "operationId": "verify_code_api_v1_auth_verify_code_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/app__routers__auth__VerifyCodeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__routers__auth__VerifyCodeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/exchange-session-token": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Exchange Session Token",
        "description": "Exchange an OTP-issued session token for full user data.\n\nCalled by the NextAuth CredentialsProvider immediately after email OTP\nverification — the frontend receives a session_token from /verify-code and\npasses it here to obtain the user object needed to populate the JWT without\nrequiring a second password entry.\n\nSecurity:\n- Session must exist in the sessions table (created by verify_code above)\n- Session must not have expired\n- Rate limited per-IP (30/min) to prevent session token enumeration,\n  consistent with /sessions/validate",
        "operationId": "exchange_session_token_api_v1_auth_exchange_session_token_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExchangeSessionTokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/oauth-signin": {
      "post": {
        "tags": [
          "Auth"
        ],
        "summary": "Oauth Signin",
        "description": "Handle OAuth sign-in/sign-up (Google, GitHub, Microsoft, Discord).\n\nSecurity enforcement:\n- Rate limited per-IP (10/min) to prevent fabricated payload abuse\n- New users: Creates account with OAuth as primary auth method\n- Existing users: Only allows sign-in if:\n  1. This provider is their primary auth method, OR\n  2. This provider is explicitly linked in linked_accounts table\n\nThis prevents unauthorized account access through OAuth email matching.",
        "operationId": "oauth_signin_api_v1_auth_oauth_signin_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthSignInRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/enterprise-invite/{token}": {
      "get": {
        "tags": [
          "Auth",
          "Auth"
        ],
        "summary": "Look up enterprise invite metadata",
        "description": "Validates an enterprise invite token and returns the associated email and organisation name. Used by the /welcome/enterprise frontend page to pre-fill the activation form. No authentication required — the token is the credential. Returns 404 if the token is not found or has expired.",
        "operationId": "enterprise_invite_info_api_v1_auth_enterprise_invite__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseInviteInfoResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/enterprise-accept": {
      "post": {
        "tags": [
          "Auth",
          "Auth"
        ],
        "summary": "Accept an enterprise invite and activate account",
        "description": "Redeems a one-time enterprise invite token. Sets the client's password, marks their email as verified, creates a session, and returns an AuthResponse so the frontend can log them in immediately. The token is deleted from Redis on success (single-use). Returns 404 if the token is not found or expired.",
        "operationId": "enterprise_accept_api_v1_auth_enterprise_accept_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnterpriseAcceptRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnterpriseAcceptResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/forgot-password": {
      "post": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Forgot Password",
        "description": "Initiate password reset flow.\n\nSends a password reset email with a token valid for 1 hour.\nAlways returns success to prevent email enumeration.\nRate limited per-IP and per-email to prevent abuse.",
        "operationId": "forgot_password_api_v1_auth_forgot_password_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ForgotPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForgotPasswordResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/reset-password": {
      "post": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Reset Password",
        "description": "Reset password using token from email.\n\nValidates token (hashed comparison) and sets new password.\nRate limited to prevent brute-force token probing.",
        "operationId": "reset_password_api_v1_auth_reset_password_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetPasswordRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResetPasswordResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/profile": {
      "get": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Get Profile",
        "description": "Get current user profile with balance-based tier and credit information.",
        "operationId": "get_profile_api_v1_auth_profile_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Update Profile",
        "description": "Update user profile.\n\nAllows updating name and email. Email changes require re-verification.",
        "operationId": "update_profile_api_v1_auth_profile_patch",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProfileRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/welcome-shown": {
      "post": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Mark Welcome Shown",
        "description": "Mark welcome banner as shown for the authenticated user.\n\nThis endpoint is called by the frontend after showing the welcome banner.\nThe flag is stored server-side for cross-device consistency.",
        "operationId": "mark_welcome_shown_api_v1_auth_welcome_shown_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/onboarding-event": {
      "post": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Record Onboarding Event",
        "description": "Record a user onboarding lifecycle event (completed or skipped).\n\nEmits ``user.onboarding_completed`` or ``user.onboarding_skipped`` to the\nlifecycle service. Both are first-only events — subsequent calls for the\nsame user are silently deduplicated.\n\nCalled by the frontend after the OnboardingModal is completed or dismissed.",
        "operationId": "record_onboarding_event_api_v1_auth_onboarding_event_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardingEventRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/change-password": {
      "post": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Change Password",
        "description": "Change password for authenticated user.\n\nRequires current password for verification.",
        "operationId": "change_password_api_v1_auth_change_password_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePasswordRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/account": {
      "delete": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Delete Account",
        "description": "Soft delete user account.\n\n- Password accounts: requires current password + confirm flag.\n- OAuth-only accounts: requires a fresh session (JWT issued within the last\n  5 minutes) to prevent a stolen long-lived JWT from deleting the account\n  without any re-authentication.",
        "operationId": "delete_account_api_v1_auth_account_delete",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/sessions": {
      "get": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Get Sessions",
        "description": "Get all active sessions for current user with device info.",
        "operationId": "get_sessions_api_v1_auth_sessions_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/app__routers__auth_extended__SessionResponse"
                  },
                  "title": "Response Get Sessions Api V1 Auth Sessions Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Revoke All Sessions",
        "description": "Revoke all sessions except current one.",
        "operationId": "revoke_all_sessions_api_v1_auth_sessions_delete",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/sessions/{session_id}/activity": {
      "patch": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Update Session Activity",
        "description": "Update last activity timestamp for a session.",
        "operationId": "update_session_activity_api_v1_auth_sessions__session_id__activity_patch",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Session Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/sessions/{session_id}": {
      "delete": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Revoke Session",
        "description": "Revoke a specific session.",
        "operationId": "revoke_session_api_v1_auth_sessions__session_id__delete",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Session Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/sessions/validate": {
      "get": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Validate Session",
        "description": "Validate whether a session token is still active.\n\nCalled by NextAuth jwt callback on token refresh cycles to detect\nrevoked sessions. Does NOT require authentication — the session\ntoken itself is the credential being validated.\n\nChecks Redis revocation list first (O(1)), falls back to DB lookup.\nReturns {\"valid\": true/false}.\n\nRate limited per-IP (30/min) to prevent session token enumeration.",
        "operationId": "validate_session_api_v1_auth_sessions_validate_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/login-history": {
      "get": {
        "tags": [
          "Auth Extended"
        ],
        "summary": "Get Login History",
        "description": "Get login history for current user.\n\nReturns up to `limit` most recent login attempts.",
        "operationId": "get_login_history_api_v1_auth_login_history_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/LoginHistoryResponse"
                  },
                  "title": "Response Get Login History Api V1 Auth Login History Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/linked-accounts": {
      "get": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Get Linked Accounts",
        "description": "Get all linked OAuth accounts for current user.",
        "operationId": "get_linked_accounts_api_v1_auth_linked_accounts_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkedAccountsListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/linked-accounts/initiate": {
      "post": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Initiate Link",
        "description": "Initiate OAuth account linking flow.\n\nGenerates a state token and returns the OAuth authorization URL.\nThe frontend should redirect to this URL to start the OAuth flow.",
        "operationId": "initiate_link_api_v1_auth_linked_accounts_initiate_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InitiateLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InitiateLinkResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/linked-accounts/callback": {
      "post": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Complete Link",
        "description": "Complete OAuth account linking after OAuth callback.\n\nCalled by NextAuth callback when linking state is detected.",
        "operationId": "complete_link_api_v1_auth_linked_accounts_callback_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/linked-accounts/complete": {
      "post": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Complete Link Public",
        "description": "Complete OAuth account linking (public endpoint).\n\nThis endpoint is called by NextAuth's signIn callback during the account\nlinking flow. Authentication is via the state token, not JWT.\n\nThe state token identifies the user who initiated the linking request.\n\nSECURITY: Rate limited to 10 requests per minute per IP to prevent\nstate token brute-force attacks.",
        "operationId": "complete_link_public_api_v1_auth_linked_accounts_complete_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompleteLinkPublicRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/linked-accounts/{provider}": {
      "delete": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Unlink Account",
        "description": "Unlink an OAuth provider from the account.\n\nCannot unlink the primary auth method unless another method is available.\nMust have at least one authentication method remaining.",
        "operationId": "unlink_account_api_v1_auth_linked_accounts__provider__delete",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Provider"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnlinkAccountResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/add-password": {
      "post": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Add Password",
        "description": "Add a password to an OAuth-only account.\n\nAllows users who signed up with OAuth to also have password-based login.",
        "operationId": "add_password_api_v1_auth_add_password_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddPasswordRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddPasswordResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/security-overview": {
      "get": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Get Security Overview",
        "description": "Get account security overview.\n\nReturns information about authentication methods and security status.",
        "operationId": "get_security_overview_api_v1_auth_security_overview_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSecurityResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/check-email-exists": {
      "get": {
        "tags": [
          "Account Linking"
        ],
        "summary": "Check Email Provider",
        "description": "Check if an email exists and what auth methods are available.\n\nUsed by sign-in flow to show appropriate options.\n\nSECURITY: Rate limited to 5 requests per minute per IP to prevent\nemail enumeration attacks. Does not reveal primary_method to reduce\ninformation leakage about user's authentication preferences.",
        "operationId": "check_email_provider_api_v1_auth_check_email_exists_get",
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "email",
              "title": "Email"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/bootstrap": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Dashboard bootstrap",
        "description": "Returns user profile, balance, and API key presence in a single call. Replaces the former two sequential calls to /auth/profile and /billing/balance on dashboard mount. Cached per user (20 s TTL with anti-stampede lock).",
        "operationId": "get_dashboard_bootstrap_api_v1_dashboard_bootstrap_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardBootstrapResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/stats": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Dashboard Stats",
        "description": "Get dashboard statistics for the current organization.\n\nNote: Currently queries by user_id. For team organizations with multiple\nmembers, this shows the requesting user's personal stats. Full org-level\naggregation requires adding organization_id to usage/credit tables.\n\nReturns:\n    - credits_available: Current credit balance\n    - credits_change_percent: % change in credits over last 30 days\n    - total_requests_month: Total requests this calendar month\n    - requests_change_percent: % change in requests vs previous 30 days\n    - cache_hit_rate: % of requests served from cache (last 30 days)\n    - avg_response_time_ms: Average response time in milliseconds",
        "operationId": "get_dashboard_stats_api_v1_dashboard_stats_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardStatsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/recent-jobs": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Recent Jobs",
        "description": "Get recent jobs for the current organization.\n\nArgs:\n    limit: Maximum number of jobs to return (1-50, default 10)\n\nReturns:\n    List of recent jobs with id, url, mode, status, credits_used, created_at",
        "operationId": "get_recent_jobs_api_v1_dashboard_recent_jobs_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/RecentJobResponse"
                  },
                  "title": "Response Get Recent Jobs Api V1 Dashboard Recent Jobs Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/jobs": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Jobs Paginated",
        "description": "Get paginated jobs for the current organization with detailed information.\n\nArgs:\n    limit: Maximum number of jobs to return (1-100, default 20)\n    offset: Number of jobs to skip for pagination\n    status: Filter by status (pending, processing, completed, failed)\n    mode: Filter by mode (light, js, pdf, ocr)\n    search: Search term to filter by URL\n    source: Filter by request source (playground = web UI, api = API calls)\n\nReturns:\n    Paginated list of jobs with detailed metadata",
        "operationId": "get_jobs_paginated_api_v1_dashboard_jobs_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by status",
              "title": "Status"
            },
            "description": "Filter by status"
          },
          {
            "name": "mode",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by mode (light, js, pdf, ocr)",
              "title": "Mode"
            },
            "description": "Filter by mode (light, js, pdf, ocr)"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Search in URL",
              "title": "Search"
            },
            "description": "Search in URL"
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by source (playground, api)",
              "title": "Source"
            },
            "description": "Filter by source (playground, api)"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobsListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/jobs/{job_id}": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Job Detail",
        "description": "Get full details of a specific job including the result.\n\nArgs:\n    job_id: UUID of the job to retrieve\n\nReturns:\n    Full job details including the complete result",
        "operationId": "get_job_detail_api_v1_dashboard_jobs__job_id__get",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Job Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/usage-timeseries": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Usage Timeseries",
        "description": "Get usage timeseries data aggregated by day or hour.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Timeseries data with:\n    - date/hour: ISO date/datetime string\n    - requests: Total requests for that period\n    - cached: Number of cached requests\n    - credits: Total credits used\n    - errors: Number of failed requests\n    - success_rate: Success rate percentage\n    - avg_latency_ms: Average response time in milliseconds",
        "operationId": "get_usage_timeseries_api_v1_dashboard_usage_timeseries_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageTimeseriesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/geo-distribution": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Geo Distribution",
        "description": "Get geographic distribution of requests.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Geographic distribution with:\n    - region: Region name (North America, Europe, Asia, Other)\n    - requests: Number of requests from region\n    - percentage: Percentage of total requests",
        "operationId": "get_geo_distribution_api_v1_dashboard_geo_distribution_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GeoDistributionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/request-types": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Request Types",
        "description": "Get request type distribution.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Request type distribution with:\n    - type: Request type (HTML, JSON, PDF, Image)\n    - requests: Number of requests of this type\n    - percentage: Percentage of total requests",
        "operationId": "get_request_types_api_v1_dashboard_request_types_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestTypesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/hourly-patterns": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Hourly Patterns",
        "description": "Get hourly request patterns.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Hourly patterns with 24 data points (0-23):\n    - hour: Hour of day (0-23)\n    - requests: Number of requests during that hour\n    - avg_latency_ms: Average response time in milliseconds",
        "operationId": "get_hourly_patterns_api_v1_dashboard_hourly_patterns_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HourlyPatternsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/top-endpoints": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Top Endpoints",
        "description": "Get top endpoints by request volume.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n    limit: Maximum number of endpoints to return (5-50, default 10)\n\nReturns:\n    Top endpoints with:\n    - endpoint: Endpoint path\n    - requests: Number of requests\n    - avg_latency_ms: Average response time in milliseconds\n    - error_rate: Error rate percentage",
        "operationId": "get_top_endpoints_api_v1_dashboard_top_endpoints_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 5,
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopEndpointsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/endpoint-stats": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Endpoint Type Stats",
        "description": "Get per-endpoint-type usage statistics (scrape/crawl/map/search).\n\nReturns request counts, credit totals, success rates, and average\nlatency grouped by endpoint type.",
        "operationId": "get_endpoint_type_stats_api_v1_dashboard_endpoint_stats_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EndpointTypeStatsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/endpoint-timeseries": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Endpoint Type Timeseries",
        "description": "Get usage timeseries broken down by endpoint type.\n\nReturns daily (or hourly) request counts and credit totals per\nendpoint type (scrape/crawl/map/search) for stacked area charts.",
        "operationId": "get_endpoint_type_timeseries_api_v1_dashboard_endpoint_timeseries_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EndpointTimeseriesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/top-consumers": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Top Consumers",
        "description": "Get top consuming domains and URLs.\n\nReturns the most frequently scraped domains and individual URLs,\nalong with their request counts and credit usage.",
        "operationId": "get_top_consumers_api_v1_dashboard_top_consumers_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TopConsumersResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/peak-hours": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Peak Hours",
        "description": "Get peak hours heatmap data.\n\nReturns request volume grouped by hour-of-day and day-of-week\nfor a GitHub-style contribution heatmap.",
        "operationId": "get_peak_hours_api_v1_dashboard_peak_hours_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PeakHoursResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/status-codes": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Status Codes",
        "description": "Get status code distribution.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Status code distribution with:\n    - individual: Top 10 individual status codes with counts and percentages\n    - grouped: Grouped by category (2xx, 3xx, 4xx, 5xx)",
        "operationId": "get_status_codes_api_v1_dashboard_status_codes_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusCodeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/detailed-logs": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Detailed Logs",
        "description": "Get detailed request logs with full metadata.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n    limit: Maximum number of records (1-1000, default 100)\n    offset: Number of records to skip for pagination (default 0)\n    source: Filter by request source (playground, api, crawl, or extraction)\n    group_by: Group results by field. Currently supports \"crawl_id\".\n\nReturns:\n    Detailed request logs with:\n    - requests: Array of request details (or groups when group_by is set)\n    - total: Total count for pagination\n    - limit: Applied limit\n    - offset: Applied offset",
        "operationId": "get_detailed_logs_api_v1_dashboard_detailed_logs_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "default": 100,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by source: playground (web UI), api (API calls), crawl (requests originating from a crawl job), or extraction (requests that used LLM extraction)",
              "title": "Source"
            },
            "description": "Filter by source: playground (web UI), api (API calls), crawl (requests originating from a crawl job), or extraction (requests that used LLM extraction)"
          },
          {
            "name": "group_by",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Group results by a field. Supported: 'crawl_id' — returns aggregated summaries (total pages, credits, domain, time range) per crawl.",
              "title": "Group By"
            },
            "description": "Group results by a field. Supported: 'crawl_id' — returns aggregated summaries (total pages, credits, domain, time range) per crawl."
          },
          {
            "name": "group_crawls",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "When true, pagination counts crawl groups as single entries instead of raw rows. Returns all child rows for each group so the frontend can expand them.",
              "default": false,
              "title": "Group Crawls"
            },
            "description": "When true, pagination counts crawl groups as single entries instead of raw rows. Returns all child rows for each group so the frontend can expand them."
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/domain-analytics": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Domain Analytics",
        "description": "Get per-domain analytics with success rate, credits, and trend.\n\nArgs:\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n    limit: Maximum number of domains to return (1-100, default 20)\n\nReturns:\n    List of domains with request counts, success rates, credits,\n    response times, and trend indicators.",
        "operationId": "get_domain_analytics_api_v1_dashboard_domain_analytics_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/domain-analytics/{domain}": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Domain Detail",
        "description": "Get detailed analytics for a single domain.\n\nArgs:\n    domain: Domain name (e.g. \"amazon.com\")\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Detailed domain stats including error breakdown and status codes.",
        "operationId": "get_domain_detail_api_v1_dashboard_domain_analytics__domain__get",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Domain"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/domain-timeseries/{domain}": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Domain Timeseries",
        "description": "Get time-series data for a specific domain.\n\nArgs:\n    domain: Domain name (e.g. \"amazon.com\")\n    days: Number of days to include (1-90, default 30 if hours not set)\n    hours: Number of hours to include (1-72, overrides days if set)\n\nReturns:\n    Time-series data with requests, successes, failures, credits,\n    and response times per day/hour.",
        "operationId": "get_domain_timeseries_api_v1_dashboard_domain_timeseries__domain__get",
        "parameters": [
          {
            "name": "domain",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Domain"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 90,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 72,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainTimeseriesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/method-breakdown": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Method Breakdown",
        "description": "Get a breakdown of scrape requests by target HTTP method.\n\nDistinguishes API relay calls (POST/PUT/PATCH/DELETE) from page scrapes\n(GET) using the dedicated http_method column added in migration 0140.\nHistorical rows (pre-migration 0140) are backfilled to GET via the\nDEFAULT clause; COALESCE is retained as a defensive fallback.\n\nIncludes both single-scrape requests (endpoint='/api/v1/scrape') and\nbatch relay requests (source='batch') to ensure non-GET HTTP method\ncalls submitted via the batch endpoint appear in the breakdown.",
        "operationId": "get_method_breakdown_api_v1_dashboard_method_breakdown_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Aggregation window in days",
              "default": 30,
              "title": "Days"
            },
            "description": "Aggregation window in days"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MethodBreakdownResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/tier-cap-insights": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get Tier Cap Insights",
        "description": "Get tier_cap_user failure insights for the current user.\n\nShows domains where scrapes failed because the user's max_tier setting\nprevented higher-tier attempts that may have succeeded. Includes playbook\nrecommendations for optimal tier settings.\n\nArgs:\n    days: Number of days to look back (1-90, default 30)\n    hours: Number of hours to look back (1-168). Takes precedence over days.\n\nReturns:\n    Per-domain tier cap failure counts with actionable recommendations.",
        "operationId": "get_tier_cap_insights_api_v1_dashboard_tier_cap_insights_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "default": 30,
              "title": "Days"
            }
          },
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 168,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TierCapInsightsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "List API keys",
        "description": "List active API keys for the current organization. Returns key metadata (name, prefix, scopes, last used) but never the full key value. Supports pagination.",
        "operationId": "list_api_keys_api_v1_api_keys_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Maximum number of keys to return (1-100)",
              "default": 50,
              "title": "Limit"
            },
            "description": "Maximum number of keys to return (1-100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of keys to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of keys to skip"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of API keys with metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Create an API key",
        "description": "Create a new API key for the current organization. The full key value is returned ONLY in this response — store it securely. Subsequent requests only return the key prefix.",
        "operationId": "create_api_key_api_v1_api_keys_post",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/APIKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyResponse"
                }
              }
            }
          },
          "409": {
            "description": "Key limit reached for this organization"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}": {
      "delete": {
        "tags": [
          "API Keys"
        ],
        "summary": "Revoke an API key",
        "description": "Soft-delete (revoke) an API key. The key is immediately invalidated and can no longer be used for authentication.",
        "operationId": "delete_api_key_api_v1_api_keys__key_id__delete",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key id",
              "title": "Key Id"
            },
            "description": "API key id"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "API key revoked"
          },
          "403": {
            "description": "Members can only delete their own keys"
          },
          "404": {
            "description": "API key not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "API Keys"
        ],
        "summary": "Rename an API key",
        "description": "Rename an API key. Owner/Admin can rename any key; members can only rename their own.",
        "operationId": "rename_api_key_api_v1_api_keys__key_id__patch",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key id",
              "title": "Key Id"
            },
            "description": "API key id"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/APIKeyRename"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "API key renamed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyResponse"
                }
              }
            }
          },
          "403": {
            "description": "Members can only rename their own keys"
          },
          "404": {
            "description": "API key not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/decrypt": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "Decrypt an API key",
        "description": "Decrypt and return the full API key value. Used by the playground when the browser cache is empty and the key needs to be recovered.",
        "operationId": "decrypt_api_key_value_api_v1_api_keys__key_id__decrypt_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key id",
              "title": "Key Id"
            },
            "description": "API key id"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key decrypted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DecryptedKeyResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not authorized to decrypt this key"
          },
          "404": {
            "description": "API key not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/regenerate": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Regenerate an API key",
        "description": "Regenerate an API key value while preserving name, limits, and metadata. The old key is immediately invalidated. The new full key value is returned ONLY in this response.",
        "operationId": "regenerate_api_key_api_v1_api_keys__key_id__regenerate_post",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key id",
              "title": "Key Id"
            },
            "description": "API key id"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key regenerated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyResponse"
                }
              }
            }
          },
          "403": {
            "description": "Not authorized to regenerate this key"
          },
          "404": {
            "description": "API key not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/legacy-status": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "Get Legacy Keys Status",
        "description": "Check if user has legacy API keys (keys without encryption) and notice status.\n\nLegacy keys are those created before the encryption feature was added.\nThese keys cannot be retrieved on new devices and must be regenerated.",
        "operationId": "get_legacy_keys_status_api_v1_api_keys_legacy_status_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LegacyKeysStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/legacy-notice-shown": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Mark Legacy Notice Shown",
        "description": "Mark the legacy keys deprecation notice as shown for this user.",
        "operationId": "mark_legacy_notice_shown_api_v1_api_keys_legacy_notice_shown_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/service-account": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Create a service account API key",
        "description": "Create a service account (M2M) API key scoped to the current organisation. Unlike user keys, service account keys have no associated user and can be restricted to specific IP ranges via an allowlist. Restricted to org owners and admins. The full key value is returned ONLY in this response — store it securely.",
        "operationId": "create_service_account_key_api_v1_api_keys_service_account_post",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ServiceAccountKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Service account key created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIKeyResponse"
                }
              }
            }
          },
          "403": {
            "description": "Insufficient permissions (owner or admin required)"
          },
          "404": {
            "description": "Key to replace not found or does not belong to this org"
          },
          "409": {
            "description": "Key name already exists in this organisation"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get Usage",
        "description": "Get usage statistics with real data from usage_tracking table.",
        "operationId": "get_usage_api_v1_usage_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageStats"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage/estimate": {
      "get": {
        "tags": [
          "Usage"
        ],
        "summary": "Get Usage Estimate",
        "description": "Get usage estimate data for the Requests Estimator feature.\n\nReturns average cost per request from a rolling window to help users\nestimate how many requests they can make with their current balance.\n\nIf the user has no usage history, falls back to Tier 1 (curl) pricing:\n- 200 microcents per request = $0.0002/request = 5,000 requests per $1\n\nArgs:\n    window_days: Rolling window size in days (default: 7, max: 30)\n\nReturns:\n    UsageEstimate with average cost and estimated remaining requests",
        "operationId": "get_usage_estimate_api_v1_usage_estimate_get",
        "parameters": [
          {
            "name": "window_days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 30,
              "minimum": 1,
              "description": "Rolling window in days (1-30)",
              "default": 7,
              "title": "Window Days"
            },
            "description": "Rolling window in days (1-30)"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageEstimate"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/limits": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Limits",
        "description": "Get spend limit configuration and status for a specific API key.",
        "operationId": "get_key_limits_api_v1_api_keys__key_id__limits_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeySpendLimitResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Set Key Limits",
        "description": "Set or update spend limits for an API key.\n\nAt least one of budget_limit_microcents or request_limit must be set.",
        "operationId": "set_key_limits_api_v1_api_keys__key_id__limits_put",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpendLimitConfig"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeySpendLimitResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Delete Key Limits",
        "description": "Remove spend limits from an API key.",
        "operationId": "delete_key_limits_api_v1_api_keys__key_id__limits_delete",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/usage": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Usage",
        "description": "Get usage summary for a specific API key.",
        "operationId": "get_key_usage_api_v1_api_keys__key_id__usage_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyUsageSummary"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/usage/timeseries": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Usage Timeseries",
        "description": "Get daily spend and request counts for a specific API key.",
        "operationId": "get_key_usage_timeseries_api_v1_api_keys__key_id__usage_timeseries_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeyUsageTimeseriesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/usage/by-tier": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Usage By Tier",
        "description": "Get usage breakdown by scraping tier for a specific API key.",
        "operationId": "get_key_usage_by_tier_api_v1_api_keys__key_id__usage_by_tier_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TierBreakdownResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/usage/errors": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Usage Errors",
        "description": "Get error type aggregation for a specific API key.",
        "operationId": "get_key_usage_errors_api_v1_api_keys__key_id__usage_errors_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorBreakdownResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{key_id}/usage/requests": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Key Usage Requests",
        "description": "Get paginated request log for a specific API key.\n\nSupports filtering by status (success/failed), tier, and domain.\nResults are ordered by created_at DESC.",
        "operationId": "get_key_usage_requests_api_v1_api_keys__key_id__usage_requests_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "API key UUID",
              "title": "Key Id"
            },
            "description": "API key UUID"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-based)",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number (1-based)"
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 10,
              "description": "Rows per page",
              "default": 50,
              "title": "Page Size"
            },
            "description": "Rows per page"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "success",
                    "failed"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by request outcome",
              "title": "Status"
            },
            "description": "Filter by request outcome"
          },
          {
            "name": "tier",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by tier_used value",
              "title": "Tier"
            },
            "description": "Filter by tier_used value"
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Substring match on extracted domain",
              "title": "Domain"
            },
            "description": "Substring match on extracted domain"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RequestLogResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/limits": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Account Limits",
        "description": "Get account-level spend limit configuration and status.",
        "operationId": "get_account_limits_api_v1_account_limits_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSpendLimitResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Set Account Limits",
        "description": "Set or update account-level spend limits.",
        "operationId": "set_account_limits_api_v1_account_limits_put",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SpendLimitConfig"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountSpendLimitResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Delete Account Limits",
        "description": "Remove account-level spend limits.",
        "operationId": "delete_account_limits_api_v1_account_limits_delete",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage/by-key": {
      "get": {
        "tags": [
          "Spend Limits"
        ],
        "summary": "Get Usage By Key",
        "description": "Get usage breakdown across all API keys for the organization.",
        "operationId": "get_usage_by_key_api_v1_usage_by_key_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Days of usage to query",
              "default": 30,
              "title": "Days"
            },
            "description": "Days of usage to query"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AllKeysUsageResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/checkout": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create a checkout session",
        "description": "Create a Stripe checkout session for adding funds to your balance. Supports multiple pricing packages. Returns a Stripe URL to redirect the user to for payment.",
        "operationId": "create_checkout_api_v1_billing_checkout_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkout session created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid amount or package"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/deposit": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create a deposit",
        "description": "Create a deposit checkout session for pay-as-you-go billing. Returns a Stripe payment URL. Credits are added to your balance after successful payment.",
        "operationId": "create_deposit_api_v1_billing_deposit_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DepositRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit session created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid deposit amount"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/balance": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get current balance",
        "description": "Get your organization's current credit balance in microcents (1,000,000 microcents = $1.00). Includes formatted display values.",
        "operationId": "get_balance_api_v1_billing_balance_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current balance in microcents with formatted display",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BalanceResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/portal": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create a Stripe portal session",
        "description": "Create a Stripe Customer Portal session where users can manage payment methods, view invoices, and update billing details.",
        "operationId": "create_portal_api_v1_billing_portal_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stripe portal session URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/subscription": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get Subscription",
        "description": "Get subscription details.\n\nDEPRECATED: AlterLab uses balance-based billing. There are no subscriptions.\nUse GET /billing/balance and GET /billing/usage/realtime instead.",
        "operationId": "get_subscription_api_v1_billing_subscription_get",
        "deprecated": true,
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/invoices": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get invoice history",
        "description": "Get your organization's invoice history, most recent first.",
        "operationId": "get_invoices_api_v1_billing_invoices_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of invoices",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/invoice/{invoice_id}": {
      "get": {
        "tags": [
          "Billing",
          "Billing"
        ],
        "summary": "Download invoice PDF (first-party, no login required)",
        "description": "Public endpoint — no session required. Validates a signed, expiring token embedded in the purchase confirmation email. Fetches the Stripe-sourced PDF server-side and streams it back as ``application/pdf`` from alterlab.io, avoiding client-side JS requirements and Firefox COOP failures.",
        "operationId": "get_invoice_pdf_api_v1_billing_invoice__invoice_id__get",
        "parameters": [
          {
            "name": "invoice_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Invoice Id"
            }
          },
          {
            "name": "uid",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Uid"
            }
          },
          {
            "name": "exp",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "title": "Exp"
            }
          },
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/deposits": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get deposit history",
        "description": "Get completed deposit history for the authenticated user, most recent first. Returns checkout sessions (mode=payment, status=complete) joined with the corresponding credit_ledger grant for balance context and payment method info.",
        "operationId": "get_deposits_api_v1_billing_deposits_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of completed deposits with payment and balance details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DepositHistoryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/receipts/{receipt_id}": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Resolve and redirect to a receipt (resolve-on-click)",
        "description": "Resolves the Stripe-hosted receipt URL for a deposit or auto-recharge row that doesn't yet have one cached, persists it, and redirects. A row that already has a cached URL redirects immediately with no Stripe API call. Scoped to the authenticated user's own rows.",
        "operationId": "get_receipt_redirect_api_v1_billing_receipts__receipt_id__get",
        "parameters": [
          {
            "name": "receipt_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Receipt Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "307": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/usage-realtime": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get real-time usage",
        "description": "Get real-time usage statistics for the current billing period. Includes request counts, credit consumption, and cost projections.",
        "operationId": "get_usage_realtime_endpoint_api_v1_billing_usage_realtime_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current period usage with projections",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageRealtimeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/usage-chart": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get usage chart data",
        "description": "Get daily usage data for charts over a configurable time window (1-365 days).",
        "operationId": "get_usage_chart_endpoint_api_v1_billing_usage_chart_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 365,
              "minimum": 1,
              "default": 30,
              "title": "Days"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Daily usage data points for charting",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageChartResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/usage-breakdown": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get usage breakdown",
        "description": "Get usage breakdown by request type for the current billing period.",
        "operationId": "get_usage_breakdown_endpoint_api_v1_billing_usage_breakdown_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage breakdown by type (scrape, crawl, search, etc.)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageBreakdownResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/cost-projection": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get cost projection",
        "description": "Get projected costs for the current billing period based on usage trends.",
        "operationId": "get_cost_projection_endpoint_api_v1_billing_cost_projection_get",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Projected cost and usage for the current period",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostProjectionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/payment-methods": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "List payment methods",
        "description": "Get your organization's saved payment methods (cards, bank accounts).",
        "operationId": "get_payment_methods_api_v1_billing_payment_methods_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of saved payment methods with last-4 and brand",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Add a payment method",
        "description": "Attach a payment method (from a completed SetupIntent) to your Stripe customer. Optionally set it as default.",
        "operationId": "add_payment_method_api_v1_billing_payment_methods_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddPaymentMethodRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment method added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentMethodResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payment method or already attached"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/setup-intent": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Create a setup intent",
        "description": "Create a Stripe SetupIntent for saving a new payment method without an immediate charge. Returns a client secret for the frontend Stripe Elements flow.",
        "operationId": "create_setup_intent_api_v1_billing_setup_intent_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stripe SetupIntent client secret",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupIntentResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/quick-deposit": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "One-click deposit with saved payment method",
        "description": "Charge a saved payment method directly via Stripe PaymentIntent (off_session=True, confirm=True). Eliminates the Stripe Checkout redirect for returning customers who already have a card on file. Credits are granted synchronously on success (non-3DS). Returns client_secret for 3DS-required cards.",
        "operationId": "quick_deposit_api_v1_billing_quick_deposit_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/QuickDepositRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit succeeded or requires 3DS action",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QuickDepositResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid amount or Stripe card error"
          },
          "403": {
            "description": "Fraud check blocked the transaction"
          },
          "404": {
            "description": "Payment method not found or not owned by user"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/payment-methods/{payment_method_id}": {
      "delete": {
        "tags": [
          "Billing"
        ],
        "summary": "Remove a payment method",
        "description": "Detach and remove a saved payment method from your account.",
        "operationId": "remove_payment_method_api_v1_billing_payment_methods__payment_method_id__delete",
        "parameters": [
          {
            "name": "payment_method_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Payment Method Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment method removed",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "404": {
            "description": "Payment method not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/payment-methods/{payment_method_id}/default": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Set default payment method",
        "description": "Set a payment method as the default for future charges and auto-recharge.",
        "operationId": "set_default_payment_method_api_v1_billing_payment_methods__payment_method_id__default_post",
        "parameters": [
          {
            "name": "payment_method_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Payment Method Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Default payment method updated",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "404": {
            "description": "Payment method not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/usage-alerts": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get usage alert settings",
        "description": "Get your current usage alert thresholds and notification preferences.",
        "operationId": "get_usage_alerts_api_v1_billing_usage_alerts_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage alert configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageAlertSettingsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Billing"
        ],
        "summary": "Update usage alert settings",
        "description": "Update usage alert thresholds and notification preferences.",
        "operationId": "update_usage_alerts_api_v1_billing_usage_alerts_put",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageAlertSettings"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated usage alert configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageAlertSettingsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/verify/initiate": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Initiate Verification",
        "description": "Initiate a 2FA verification challenge for a protected billing action.\n\nReturns a challenge ID and sends a verification code via the specified method.",
        "operationId": "initiate_verification_api_v1_billing_verify_initiate_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerificationChallengeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerificationChallengeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/verify/confirm": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Verify Code",
        "description": "Verify a 2FA code.",
        "operationId": "verify_code_api_v1_billing_verify_confirm_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/app__schemas__billing__VerifyCodeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__billing__VerifyCodeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/audit-log": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get billing audit log",
        "description": "Get a paginated audit trail of billing actions (deposits, refunds, etc.).",
        "operationId": "get_audit_log_api_v1_billing_audit_log_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated billing audit log entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/recent-activity": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get recent billing activity",
        "description": "Get recent billing activity for dashboard display.",
        "operationId": "get_recent_activity_api_v1_billing_recent_activity_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "default": 10,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent billing activity entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecentActivityResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/credit-transactions": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get credit transactions",
        "description": "Get credit ledger transactions (debits, refunds, grants) for your account. Supports filtering by reference type (e.g. 'crawl', 'scrape').",
        "operationId": "get_credit_transactions_api_v1_billing_credit_transactions_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "reference_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by reference_type (e.g. 'crawl')",
              "title": "Reference Type"
            },
            "description": "Filter by reference_type (e.g. 'crawl')"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated credit transaction history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditTransactionsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/change-plan": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Change Plan",
        "description": "Change subscription plan.\n\nDEPRECATED: AlterLab uses balance-based billing. There are no subscription\nplans to change. Scraping tier is determined automatically by each request.\nUse POST /billing/deposit to add funds to your balance.",
        "operationId": "change_plan_api_v1_billing_change_plan_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/auto-recharge": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get auto-recharge settings",
        "description": "Get your current auto-recharge configuration: threshold, recharge amount, and payment method.",
        "operationId": "get_auto_recharge_settings_api_v1_billing_auto_recharge_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Auto-recharge configuration",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoRechargeSettingsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Billing"
        ],
        "summary": "Update auto-recharge settings",
        "description": "Configure automatic balance top-ups. When your balance drops below the threshold, the specified amount is charged to your default payment method.",
        "operationId": "update_auto_recharge_settings_api_v1_billing_auto_recharge_put",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AutoRechargeSettingsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settings updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoRechargeSettingsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid threshold or amount"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Billing"
        ],
        "summary": "Disable auto-recharge",
        "description": "Disable auto-recharge and clear the saved payment method configuration.",
        "operationId": "delete_auto_recharge_settings_api_v1_billing_auto_recharge_delete",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Auto-recharge disabled",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/auto-recharge/test": {
      "post": {
        "tags": [
          "Billing"
        ],
        "summary": "Test auto-recharge",
        "description": "Perform a dry-run auto-recharge to verify payment method and configuration are valid without actually charging.",
        "operationId": "test_auto_recharge_api_v1_billing_auto_recharge_test_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Test result with validation status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutoRechargeTestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/auto-recharge/history": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get auto-recharge history",
        "description": "Get paginated history of auto-recharge attempts for your account.",
        "operationId": "get_recharge_history_api_v1_billing_auto_recharge_history_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number"
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Results per page",
              "default": 20,
              "title": "Per Page"
            },
            "description": "Results per page"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of auto-recharge events",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/b2b/summary": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get B2B billing summary",
        "description": "Returns usage and cost summary for the current period for enterprise B2B tenants. Requires an active tenant billing configuration (enterprise contract). Returns 404 for self-serve organizations.",
        "operationId": "get_b2b_billing_summary_api_v1_billing_b2b_summary_get",
        "parameters": [
          {
            "name": "period_start",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Period start (inclusive, UTC). Defaults to first day of current calendar month.",
              "title": "Period Start"
            },
            "description": "Period start (inclusive, UTC). Defaults to first day of current calendar month."
          },
          {
            "name": "period_end",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Period end (inclusive, UTC). Defaults to last moment of current calendar month.",
              "title": "Period End"
            },
            "description": "Period end (inclusive, UTC). Defaults to last moment of current calendar month."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Billing summary with per-tier cost breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/B2BBillingSummaryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/track/click": {
      "post": {
        "tags": [
          "Affiliates"
        ],
        "summary": "Record an affiliate click",
        "description": "Record a click attributed to an affiliate referral link.\n\nCalled when a visitor arrives via a referral link (``?ref=CODE``).\nThis endpoint is **unauthenticated** — referral links are clicked by\nanonymous visitors who may not yet have accounts.\n\nPrivacy:\n    - Raw IP addresses and User-Agent strings are **never** stored.\n    - Both are SHA-256 hashed before persistence.\n\nRate limiting:\n    - Maximum ``10`` requests per IP per hour (Redis-backed).\n    - Fail-open: if Redis is unavailable the rate limit is skipped\n      so that a Redis outage does not block click recording.\n\nDeduplication:\n    - The same visitor (identified by ``ip_hash``) is counted at most once\n      per affiliate per ``24``-hour window.\n    - A deduplicated request returns HTTP 200 with ``recorded=false``.\n\nReturns:\n    ``recorded=true`` if a new click row was inserted.\n    ``recorded=false`` if the click was deduplicated (silent skip).",
        "operationId": "record_affiliate_click_api_v1_affiliates_track_click_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateClickRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateClickResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/apply": {
      "post": {
        "tags": [
          "Affiliates"
        ],
        "summary": "Apply to become an affiliate",
        "description": "Submit an affiliate application.\n\nCreates an affiliate record with status=pending. The user's referral code\nis generated immediately but the affiliate cannot earn commissions until\nan admin approves the application (status → active).\n\nReturns 409 if the user has already applied.",
        "operationId": "apply_affiliate_api_v1_affiliates_apply_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AffiliateApplyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateApplyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me": {
      "get": {
        "tags": [
          "Affiliates"
        ],
        "summary": "Get my affiliate profile",
        "description": "Return the authenticated user's affiliate profile, including referral link\nand earnings breakdown.\n\nReturns 404 if the user is not an affiliate.",
        "operationId": "get_my_affiliate_api_v1_affiliates_me_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateProfileResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me/stats": {
      "get": {
        "tags": [
          "Affiliates"
        ],
        "summary": "Get my affiliate stats",
        "description": "Return click and conversion statistics for the authenticated affiliate.\n\nClick counts are windowed (30-day and 90-day). Conversion counts are\nbroken down by status. Earnings are pulled from the affiliate record.\n\nReturns 404 if the user is not an affiliate.",
        "operationId": "get_my_stats_api_v1_affiliates_me_stats_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateStatsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/affiliates/me/conversions": {
      "get": {
        "tags": [
          "Affiliates"
        ],
        "summary": "List my conversion history",
        "description": "Return paginated conversion history for the authenticated affiliate.\n\nConversions are sorted by created_at descending (newest first). Each\nconversion includes the commission amount, status, and an anonymized\nreferred user token (first 8 characters of the referred user's UUID).\n\nReturns 404 if the user is not an affiliate.",
        "operationId": "get_my_conversions_api_v1_affiliates_me_conversions_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^(pending|approved|paid|reversed)$"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by conversion status",
              "title": "Status"
            },
            "description": "Filter by conversion status"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number"
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Items per page",
              "default": 20,
              "title": "Page Size"
            },
            "description": "Items per page"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AffiliateConversionsListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/trial": {
      "post": {
        "tags": [
          "Agent Trial"
        ],
        "summary": "Issue a zero-signup agent trial token",
        "description": "Issue a scoped, time-limited, credit-capped API key with no signup.\n\nIntentionally unauthenticated — that is the entire point of this\nendpoint. Abuse is bounded two ways:\n\n1. **Issuance**: at most ``TRIAL_ISSUE_MAX_PER_IP`` tokens per IP per\n   ``TRIAL_ISSUE_WINDOW_SECONDS`` (checked here, before any DB write).\n2. **Usage**: each issued token is capped at ``TRIAL_REQUEST_CAP``\n   requests total, enforced per-key in ``deps.get_current_user`` via\n   ``app.security.trial_tokens.enforce_trial_credit_cap`` (Redis).\n   Downstream endpoints also debit the pool user's Postgres balance,\n   but the Redis cap fires first and is the primary enforcer — one\n   abusive trial token cannot exhaust budget shared with other tokens.\n\nWorst-case cost exposure: ``TRIAL_ISSUE_MAX_PER_IP`` tokens/IP/window ×\n``TRIAL_REQUEST_CAP`` requests/token × cheapest-tier (T1 HTTP) cost per\nrequest, times however many distinct IPs an attacker controls — bounded\nper-IP and per-key, with no cross-key amplification since the shared\npool organisation's own credit balance is a fixed, manually-topped-up\nceiling and is not linked to Stripe.\n\n**Trial-to-full-account conversion**: this endpoint issues a\nself-contained trial key with no persistent per-agent state to migrate.\nOnce a human signs up and adds billing, they create a normal user-owned\nor service-account key through the existing\n``POST /api/v1/api-keys`` flow (which already supports\n``replaces_key_id`` for zero-downtime rotation) and simply stop using\nthe trial key — no migration endpoint is needed because the trial key\nnever accrued account-specific data.",
        "operationId": "create_agent_trial_token_api_v1_agent_trial_post",
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentTrialResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referral/my-link": {
      "get": {
        "tags": [
          "Referral"
        ],
        "summary": "Get My Referral Link",
        "description": "Get or create the authenticated user's referral link.\n\nEach user gets one unique referral link. If none exists yet,\none is automatically created on first access.",
        "operationId": "get_my_referral_link_api_v1_referral_my_link_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralLinkResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referral/stats": {
      "get": {
        "tags": [
          "Referral"
        ],
        "summary": "Get Referral Stats",
        "description": "Get referral performance stats for the authenticated user.\n\nShows total referrals, successful conversions, and credits earned.\nCreates a referral link if the user doesn't have one yet.",
        "operationId": "get_referral_stats_api_v1_referral_stats_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralStatsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referral/validate-code": {
      "post": {
        "tags": [
          "Referral"
        ],
        "summary": "Validate Code",
        "description": "Validate a referral code (public — used during signup flow).\n\nThis endpoint does NOT require authentication since it's called\nbefore the user has an account.",
        "operationId": "validate_code_api_v1_referral_validate_code_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReferralValidateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralValidateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/billing/promo/validate": {
      "post": {
        "tags": [
          "Promo Codes"
        ],
        "summary": "Validate Promo Code",
        "description": "Validate a promo code for the current user.\n\nRate-limited to 5 failed attempts per 10 minutes per user to prevent\nbrute-force enumeration of valid codes. Only failed validations count\nagainst the limit — successful validations do not consume attempts.",
        "operationId": "validate_promo_code_api_v1_billing_promo_validate_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PromoCodeValidateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PromoCodeValidateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referrals/code": {
      "get": {
        "tags": [
          "Referrals"
        ],
        "summary": "Get or create referral code",
        "description": "Return the authenticated user's referral code, creating it if it does not yet exist.\n\nIdempotent — safe to call multiple times; always returns the same code.",
        "operationId": "get_referral_code_api_v1_referrals_code_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The caller's referral code (created on first call)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralCodeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referrals/stats": {
      "get": {
        "tags": [
          "Referrals"
        ],
        "summary": "Get referral dashboard stats",
        "description": "Return aggregate referral statistics for the authenticated user.\n\nIf the user has no referral code yet, it is created automatically before\nreturning stats (same as GET /referrals/code).",
        "operationId": "get_referral_stats_api_v1_referrals_stats_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregate stats: tier, commission rate, signups, earnings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralStatsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/referrals/events": {
      "get": {
        "tags": [
          "Referrals"
        ],
        "summary": "Get referral event history",
        "description": "Return paginated referral event history for the authenticated user.\n\nEvents are sorted newest-first. Returns an empty list if the user has no\nreferral code.",
        "operationId": "get_referral_events_api_v1_referrals_events_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-indexed)",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number (1-indexed)"
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Results per page",
              "default": 20,
              "title": "Page Size"
            },
            "description": "Results per page"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of signup and commission events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReferralEventsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "List Organizations",
        "description": "List all organizations the current user is a member of.",
        "operationId": "list_organizations_api_v1_organizations_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Create Organization",
        "description": "Create a new organization.",
        "operationId": "create_organization_api_v1_organizations_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationWithRole"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/default": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Default Organization",
        "description": "Get the user's default organization.",
        "operationId": "get_default_organization_api_v1_organizations_default_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DefaultOrganizationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Set Default Organization",
        "description": "Set the user's default organization.",
        "operationId": "set_default_organization_api_v1_organizations_default_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetDefaultOrganizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DefaultOrganizationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Organization",
        "description": "Get organization details.",
        "operationId": "get_organization_api_v1_organizations__org_id__get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationWithRole"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Update Organization",
        "description": "Update organization details. Requires admin or owner role.",
        "operationId": "update_organization_api_v1_organizations__org_id__patch",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrganizationUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationWithRole"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Delete Organization",
        "description": "Delete an organization. Requires owner role.",
        "operationId": "delete_organization_api_v1_organizations__org_id__delete",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/billing-identity": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Billing Identity",
        "description": "Get the org's billing identity: legal name, address, tax IDs.\n\nPersonal orgs resolve to the user's self-serve billing_customer; team\norgs resolve to the org-keyed billing_customer. Requires org membership\n(any role) to view.",
        "operationId": "get_billing_identity_api_v1_organizations__org_id__billing_identity_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingIdentityResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Update Billing Identity",
        "description": "Update the org's billing identity and write it through to Stripe.\n\nRequires admin or owner role. Stripe is updated first, and the DB write\nonly happens after Stripe accepts the change — but the DB is *not*\nguaranteed untouched on failure. If the Stripe write-through raises\n`StripeError`, the `except` block below does a best-effort reconciliation:\nit re-reads whatever Stripe actually holds for every field this request\ntouched and persists that into the DB, so a partial Stripe-side success\n(e.g. `Customer.modify` committed before a later tax_id call failed)\ndoesn't leave the DB stale. This isn't atomicity — Stripe has no\ntransaction spanning `Customer.modify` and the tax_id sub-resource — it's\nthe DB self-healing to mirror Stripe's true state either way.\n`Customer.modify` handles name/address; tax_ids uses the Tax IDs\nsub-resource (create-only via tax_id_data on Customer.create, so updates\ngo through Customer.create_tax_id/delete_tax_id instead).",
        "operationId": "update_billing_identity_api_v1_organizations__org_id__billing_identity_put",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BillingIdentityUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingIdentityResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/members": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "List Members",
        "description": "List all members of an organization.",
        "operationId": "list_members_api_v1_organizations__org_id__members_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 50,
              "title": "Page Size"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemberListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/members/{member_user_id}": {
      "patch": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Update Member Role",
        "description": "Update a member's role. Requires admin or owner role.",
        "operationId": "update_member_role_api_v1_organizations__org_id__members__member_user_id__patch",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "member_user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Member User Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MemberRoleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationMemberResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Remove Member",
        "description": "Remove a member from the organization. Requires admin or owner role.",
        "operationId": "remove_member_api_v1_organizations__org_id__members__member_user_id__delete",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "member_user_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Member User Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/leave": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Leave Organization",
        "description": "Leave an organization.",
        "operationId": "leave_organization_api_v1_organizations__org_id__leave_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/invitations": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Create Invitation",
        "description": "Invite a user to the organization. Requires admin or owner role.",
        "operationId": "create_invitation_api_v1_organizations__org_id__invitations_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvitationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "List Invitations",
        "description": "List pending invitations. Requires admin or owner role.",
        "operationId": "list_invitations_api_v1_organizations__org_id__invitations_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PendingInvitationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/invitations/{invitation_id}": {
      "delete": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Cancel Invitation",
        "description": "Cancel a pending invitation. Requires admin or owner role.",
        "operationId": "cancel_invitation_api_v1_organizations__org_id__invitations__invitation_id__delete",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "invitation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Invitation Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/invitations/{invitation_id}/resend": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Resend Invitation",
        "description": "Resend an invitation email. Requires admin or owner role.",
        "operationId": "resend_invitation_api_v1_organizations__org_id__invitations__invitation_id__resend_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "invitation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Invitation Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/invitations/{token}": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Invitation By Token",
        "description": "Get invitation details by token (public endpoint).",
        "operationId": "get_invitation_by_token_api_v1_organizations_invitations__token__get",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationPublicResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/invitations/{token}/accept": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Accept Invitation",
        "description": "Accept an invitation to join an organization.",
        "operationId": "accept_invitation_api_v1_organizations_invitations__token__accept_post",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationAcceptResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/invitations/{token}/decline": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Decline Invitation",
        "description": "Decline an invitation.",
        "operationId": "decline_invitation_api_v1_organizations_invitations__token__decline_post",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Token"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/transfer-ownership": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Transfer Ownership",
        "description": "Transfer organization ownership to another member. Requires owner role.",
        "operationId": "transfer_ownership_api_v1_organizations__org_id__transfer_ownership_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TransferOwnershipRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransferOwnershipResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/stats": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Organization Stats",
        "description": "Get organization statistics.",
        "operationId": "get_organization_stats_api_v1_organizations__org_id__stats_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrganizationStats"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/audit-logs": {
      "get": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Get Organization Audit Logs",
        "description": "Get organization audit logs. Requires admin or owner role.",
        "operationId": "get_organization_audit_logs_api_v1_organizations__org_id__audit_logs_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "action",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by action type",
              "title": "Action"
            },
            "description": "Filter by action type"
          },
          {
            "name": "actor_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by actor",
              "title": "Actor Id"
            },
            "description": "Filter by actor"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Number of entries to return",
              "default": 50,
              "title": "Limit"
            },
            "description": "Number of entries to return"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of entries to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of entries to skip"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/beta-features/{slug}/enable-all": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Enable a beta feature for all org members",
        "description": "Bulk-enables a beta feature for all current organization members by creating ``user_beta_features`` rows for members who do not already have the feature enabled. Requires admin or owner role. Only works for features with status ``beta`` — hidden features cannot be bulk-enabled; GA features are already enabled for everyone. Members who join the organization after this call must opt in individually.",
        "operationId": "enable_beta_for_org_api_v1_organizations__org_id__beta_features__slug__enable_all_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgBetaFeatureBulkResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/organizations/{org_id}/beta-features/{slug}/disable-all": {
      "post": {
        "tags": [
          "Organizations",
          "organizations"
        ],
        "summary": "Disable a beta feature for all org members",
        "description": "Bulk-disables a beta feature for all current organization members by removing their ``user_beta_features`` rows. Requires admin or owner role. Individual members can re-enable the feature themselves afterwards. GA features cannot be disabled — they are always enabled for everyone.",
        "operationId": "disable_beta_for_org_api_v1_organizations__org_id__beta_features__slug__disable_all_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgBetaFeatureBulkResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/favicon": {
      "get": {
        "tags": [
          "Favicon"
        ],
        "summary": "Get Favicon",
        "description": "Get a cached favicon for a domain.\n\nFetches the favicon from Google's favicon service and caches it in Redis.\nReturns a cached version on subsequent requests.\n\nArgs:\n    domain: The domain to fetch favicon for\n    size: The desired favicon size (16-256 pixels)\n\nReturns:\n    PNG image response with the favicon",
        "operationId": "get_favicon_api_v1_favicon_get",
        "parameters": [
          {
            "name": "domain",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Domain to get favicon for (e.g., 'example.com')",
              "title": "Domain"
            },
            "description": "Domain to get favicon for (e.g., 'example.com')"
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 256,
              "minimum": 16,
              "description": "Favicon size in pixels",
              "default": 32,
              "title": "Size"
            },
            "description": "Favicon size in pixels"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/favicon/batch": {
      "get": {
        "tags": [
          "Favicon"
        ],
        "summary": "Get Favicons Batch",
        "description": "Get favicon URLs for multiple domains.\n\nReturns a mapping of domain -> favicon URL for use in the frontend.\nThis allows batch prefetching of favicons.\n\nArgs:\n    domains: Comma-separated list of domains\n    size: The desired favicon size\n\nReturns:\n    Dict mapping domain -> favicon URL",
        "operationId": "get_favicons_batch_api_v1_favicon_batch_get",
        "parameters": [
          {
            "name": "domains",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Comma-separated list of domains",
              "title": "Domains"
            },
            "description": "Comma-separated list of domains"
          },
          {
            "name": "size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 256,
              "minimum": 16,
              "description": "Favicon size in pixels",
              "default": 32,
              "title": "Size"
            },
            "description": "Favicon size in pixels"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Favicons Batch Api V1 Favicon Batch Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/oauth/authorize": {
      "post": {
        "tags": [
          "OAuth2"
        ],
        "summary": "Oauth Authorize",
        "description": "Generate an OAuth2 authorization code.\n\nCalled by the web app after the user authenticates via NextAuth.\nThe web app sends the user's JWT, we generate a code and return it.\nThe web app then redirects the user to the third-party callback URL.\n\nRequires: Authorization: Bearer <NextAuth JWT>",
        "operationId": "oauth_authorize_api_v1_oauth_authorize_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthorizeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorizeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/oauth/token": {
      "post": {
        "tags": [
          "OAuth2"
        ],
        "summary": "Oauth Token",
        "description": "Exchange an authorization code for an API key (access_token).\n\nThis is the standard OAuth2 token exchange endpoint.\nThe access_token returned is a real AlterLab API key (sk_live_*).\nIt does not expire (API keys are permanent until revoked).\n\nNo Authorization header required — uses client_id + client_secret.",
        "operationId": "oauth_token_api_v1_oauth_token_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connections/connect/{provider}": {
      "post": {
        "tags": [
          "OAuth2 Connections"
        ],
        "summary": "Initiate OAuth2 PKCE flow for a provider",
        "description": "Generate an authorization URL and store PKCE state in Redis.\n\nThe caller should redirect the user to ``authorization_url``.\nThe ``state`` value will be echoed back on the callback.\n\n- Unknown provider → 404\n- Provider not configured (missing env vars) → 503\n- Rate limit exceeded → 429\n- User abuse-flagged for this provider → 403\n- Invalid scope override (not in provider whitelist) → 422",
        "operationId": "initiate_connection_api_v1_connections_connect__provider__post",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Provider"
            }
          },
          {
            "name": "scopes",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Space-separated scope override",
              "title": "Scopes"
            },
            "description": "Space-separated scope override"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connections/callback/{provider}": {
      "get": {
        "tags": [
          "OAuth2 Connections"
        ],
        "summary": "Handle OAuth2 authorization callback",
        "description": "Exchange the authorization code for access/refresh tokens.\n\nValidates the PKCE state from Redis (atomic getdel — prevents replay attacks),\nexchanges the code with the provider's token endpoint, and stores encrypted tokens.\n\n- Invalid/expired state → 400\n- Token exchange failure → 400\n- Unknown provider → 404",
        "operationId": "handle_callback_api_v1_connections_callback__provider__get",
        "parameters": [
          {
            "name": "provider",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Provider"
            }
          },
          {
            "name": "code",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Authorization code from provider",
              "title": "Code"
            },
            "description": "Authorization code from provider"
          },
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "State token echoed from initiation",
              "title": "State"
            },
            "description": "State token echoed from initiation"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionInfo"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connections": {
      "get": {
        "tags": [
          "OAuth2 Connections"
        ],
        "summary": "List active OAuth2 connections",
        "description": "Return all active (non-disconnected) connections for the authenticated user.\n\nTokens are never included in the response.",
        "operationId": "list_connections_api_v1_connections_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connections/{connection_id}": {
      "delete": {
        "tags": [
          "OAuth2 Connections"
        ],
        "summary": "Disconnect an OAuth2 provider",
        "description": "Soft-delete an OAuth2 connection.\n\nSets ``disconnected_at`` to now. The connection remains in the DB for audit\npurposes but is excluded from list/callback operations.\n\n- Connection not found or not owned by user → 404\n- Already disconnected → 404",
        "operationId": "disconnect_connection_api_v1_connections__connection_id__delete",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Connection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisconnectResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connections/{connection_id}/refresh": {
      "post": {
        "tags": [
          "OAuth2 Connections"
        ],
        "summary": "On-demand refresh of an OAuth2 access token",
        "description": "Exchange the stored refresh token for a new access token on demand.\n\nUseful when the client detects an expired token mid-workflow and wants to\nrefresh it immediately rather than waiting for the background sweep.\n\nA Redis distributed lock prevents a concurrent background sweep from\nrefreshing the same connection at the same time.\n\n- Connection not found or not owned by user → 404\n- Already disconnected → 404\n- No refresh token stored → 400\n- Provider rejects the refresh token → 400\n- Provider unreachable → 502",
        "operationId": "refresh_connection_api_v1_connections__connection_id__refresh_post",
        "parameters": [
          {
            "name": "connection_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Connection Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectionInfo"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scrape": {
      "post": {
        "tags": [
          "Scraping (Unified)"
        ],
        "summary": "Scrape a web page",
        "description": "Scrape a single URL with intelligent tier escalation. The engine automatically selects the cheapest scraping tier that succeeds (curl → HTTP → stealth → browser → captcha solver) and only charges for the tier actually used.\n\n**Modes**: `auto` (default — detect best mode), `html`, `js` (headless browser), `pdf`, `ocr`.\n\n**Sync vs async**: `sync=true` (default) blocks until the result is ready (up to 120 s) and returns **200** with content. `sync=false` returns **202** immediately with a `job_id` for polling via `GET /v1/jobs/{job_id}`.\n\n**Cost**: 1–20 credits per request depending on the tier used. Use `cost_controls.max_cost` to cap spend.\n\n**Agent intent headers (opt-in)**: an agent (or its operator) may optionally send `X-Agent-Intent`, `X-Agent-Context`, and/or `X-Agent-Feedback` to tell AlterLab what it's trying to do and what already failed. All three are independent, free-text, capped at 500 characters (truncated, never rejected), and stored as opaque text alongside this request's implicit retry/error telemetry signal for later analysis — content is never parsed or executed. Omitting all three changes nothing about request handling.",
        "operationId": "unified_scrape_api_v1_scrape_post",
        "parameters": [
          {
            "name": "template",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Scrape template slug. When provided, the template's request_config is merged into the request body (caller-provided fields take precedence). Example: ?template=amazon-product",
              "title": "Template"
            },
            "description": "Scrape template slug. When provided, the template's request_config is merged into the request body (caller-provided fields take precedence). Example: ?template=amazon-product"
          },
          {
            "name": "X-Marketplace-Provider",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Marketplace-Provider"
            }
          },
          {
            "name": "X-AlterLab-Source",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Alterlab-Source"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "X-Agent-Intent",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Agent-Intent"
            }
          },
          {
            "name": "X-Agent-Context",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Agent-Context"
            }
          },
          {
            "name": "X-Agent-Feedback",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Agent-Feedback"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnifiedScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scrape completed (sync mode) — content is in the response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnifiedScrapeResponse"
                }
              }
            }
          },
          "202": {
            "description": "Job accepted (async mode) — poll GET /v1/jobs/{job_id} for results"
          },
          "402": {
            "description": "No API key provided (machine-readable registration link returned), or an authenticated caller has insufficient credits"
          },
          "422": {
            "description": "Invalid URL or request parameters"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/api/v1/scrape/estimate": {
      "post": {
        "tags": [
          "Scraping (Unified)"
        ],
        "summary": "Estimate scrape cost (agent pricing-transparency primitive)",
        "description": "Machine-readable pricing manifest for a single URL: predicted tier, credit cost, a hard cost ceiling (max_possible_credits), and a human-readable reasoning string — all without actually scraping. This is the primitive to call for pre-flight budget decisions before committing credits, whether from a UI cost preview or an autonomous agent deciding whether a request is worth its cost.",
        "operationId": "estimate_cost_api_v1_scrape_estimate_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnifiedScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cost estimate returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CostEstimate"
                }
              }
            }
          },
          "422": {
            "description": "Invalid URL"
          }
        }
      }
    },
    "/api/v1/search": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Search the web",
        "description": "Find relevant pages by query. Optionally scrape result pages for content.",
        "operationId": "search_api_v1_search_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Search results returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "202": {
            "description": "Search results found, scraping in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchWithScrapeResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "503": {
            "description": "Search service unavailable"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/batch": {
      "post": {
        "tags": [
          "Search"
        ],
        "summary": "Submit a batch of search queries",
        "description": "Submit up to 50 queries for async parallel SERP processing. Requires Growth+ balance tier ($50+). Poll GET /v1/search/batch/{batch_id} for results. Optionally receive results via webhook when all queries complete.",
        "operationId": "create_search_batch_api_v1_search_batch_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchSearchRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchSearchResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/batch/{batch_id}": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Poll batch search status",
        "description": "Poll the status of a batch search submitted via POST /v1/search/batch. Returns per-query results as they complete. When all queries are done and a webhook_url was provided, fires a webhook.",
        "operationId": "get_search_batch_status_api_v1_search_batch__batch_id__get",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Batch Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchSearchStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/{search_id}": {
      "get": {
        "tags": [
          "Search"
        ],
        "summary": "Get search status",
        "description": "Poll for search+scrape progress when scrape_results was true.",
        "operationId": "get_search_status_api_v1_search__search_id__get",
        "parameters": [
          {
            "name": "search_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Search Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp": {
      "post": {
        "tags": [
          "SERP"
        ],
        "summary": "Scrape a search engine results page",
        "description": "Execute a Google or Bing SERP scrape with browser-tier rendering. Captures organic results, paid ads (text, shopping, local), rich results (featured snippets, knowledge panels, PAA), and vertical results. Use include_ads=true (default) for ad extraction — the primary use case. For lightweight searches without ads, use POST /v1/search instead.",
        "operationId": "search_serp_api_v1_serp_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SerpRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SERP results returned successfully (sync mode)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpResponse"
                }
              }
            }
          },
          "202": {
            "description": "SERP request accepted for async processing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpStatusResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "503": {
            "description": "SERP scrape failed or timed out"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/history": {
      "get": {
        "tags": [
          "SERP"
        ],
        "summary": "Get SERP result history for keyword tracking",
        "description": "Retrieve historical SERP snapshots for a given query, enabling keyword tracking over time. Returns time-series data with change detection (new/dropped advertisers, position shifts). Each successful SERP scrape is automatically stored as a snapshot.",
        "operationId": "get_serp_history_api_v1_serp_history_get",
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Query"
            }
          },
          {
            "name": "search_engine",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "google",
              "title": "Search Engine"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Country"
            }
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Language"
            }
          },
          {
            "name": "from_date",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "title": "From Date"
            }
          },
          {
            "name": "to_date",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "title": "To Date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "include_changes",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": true,
              "title": "Include Changes"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SERP history returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpHistoryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/sessions": {
      "post": {
        "tags": [
          "SERP"
        ],
        "summary": "Register a persistent SERP session",
        "description": "Register a persistent browser session from the SERP session pool for reuse across multiple scrape requests.  Pass the returned session_id in the session_id field of POST /v1/serp to route searches through the same browser context, preserving cookies, fingerprints, and search history signals.\n\nSessions are drawn from the shared session pool maintained by the worker.  Rate limited to 10 creates per user per 24 hours to prevent pool exhaustion.",
        "operationId": "create_serp_session_api_v1_serp_sessions_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SerpSessionCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session registered successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpSessionCreateResponse"
                }
              }
            }
          },
          "200": {
            "description": "Session already registered — existing session returned"
          },
          "429": {
            "description": "Session creation rate limit exceeded (max 10/day)"
          },
          "503": {
            "description": "No active session available in pool — pool may be warming"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "SERP"
        ],
        "summary": "List persistent SERP sessions",
        "description": "List all persistent SERP sessions registered by the authenticated user, enriched with live health metrics from the session pool.",
        "operationId": "list_serp_sessions_api_v1_serp_sessions_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpSessionListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/sessions/{session_id}": {
      "get": {
        "tags": [
          "SERP"
        ],
        "summary": "Inspect a persistent SERP session",
        "description": "Return detailed health metrics for a specific SERP session registered by the user.",
        "operationId": "get_serp_session_api_v1_serp_sessions__session_id__get",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "Session ID",
              "title": "Session Id"
            },
            "description": "Session ID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session health metrics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpSessionInfo"
                }
              }
            }
          },
          "404": {
            "description": "Session not found or not owned by this user"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "SERP"
        ],
        "summary": "Retire a persistent SERP session",
        "description": "Force-retire a persistent SERP session.  The retire command is written to Redis and the worker's session pool health loop (runs every 30 s) will pick it up, transitioning the session to the ROTATING state and spawning a fresh replacement.\n\nReturns 202 Accepted — the actual retirement happens asynchronously within ~30 seconds.",
        "operationId": "retire_serp_session_api_v1_serp_sessions__session_id__delete",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "Session ID to retire",
              "title": "Session Id"
            },
            "description": "Session ID to retire"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Retire command accepted — worker will retire the session within 30 s",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Retire Serp Session Api V1 Serp Sessions  Session Id  Delete"
                }
              }
            }
          },
          "404": {
            "description": "Session not found or not owned by this user"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/{serp_id}": {
      "get": {
        "tags": [
          "SERP"
        ],
        "summary": "Poll SERP request status",
        "description": "Poll the status of an async SERP request submitted via POST /v1/serp with a webhook_url. Returns processing/completed/failed status. When completed, the full SerpResponse is embedded in the result field. Results expire after 2 hours matching the underlying job TTL.",
        "operationId": "get_serp_status_api_v1_serp__serp_id__get",
        "parameters": [
          {
            "name": "serp_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "SERP request ID returned from POST /v1/serp",
              "title": "Serp Id"
            },
            "description": "SERP request ID returned from POST /v1/serp"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SERP request status and results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "SERP request not found or expired"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/batch": {
      "post": {
        "tags": [
          "SERP"
        ],
        "summary": "Submit batch SERP queries",
        "description": "Submit up to 50 SERP queries for asynchronous parallel processing. Each query can override batch-level defaults for device, country, and ad settings. Results are delivered via polling or webhook.",
        "operationId": "create_serp_batch_api_v1_serp_batch_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SerpBatchRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Batch accepted for processing",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpBatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid webhook URL"
          },
          "402": {
            "description": "Insufficient credits"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/serp/batch/{batch_id}": {
      "get": {
        "tags": [
          "SERP"
        ],
        "summary": "Poll batch SERP status",
        "description": "Check the status of a batch SERP request and retrieve results as they complete.",
        "operationId": "get_serp_batch_status_api_v1_serp_batch__batch_id__get",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "Batch ID returned from POST /v1/serp/batch",
              "title": "Batch Id"
            },
            "description": "Batch ID returned from POST /v1/serp/batch"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch status and results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SerpBatchStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Batch not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extract/estimate": {
      "get": {
        "tags": [
          "Extraction"
        ],
        "summary": "Estimate extraction cost",
        "description": "Returns the estimated cost for a POST /v1/extract call before committing to it. Useful for displaying cost previews in client UIs or CLI tools.\n\nCost is clamped to a minimum of $0.001 (100 µ¢) and a maximum of $0.50 (50,000 µ¢). When a BYOK key is registered, the LLM invocation fee is 300 µ¢ (flat orchestration fee). Without a registered BYOK key the platform rate of 1000 µ¢ applies.",
        "operationId": "estimate_extraction_cost_api_v1_extract_estimate_get",
        "parameters": [
          {
            "name": "content_length",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer",
              "maximum": 500000,
              "minimum": 1,
              "title": "Content Length"
            }
          },
          {
            "name": "has_extraction_prompt",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Has Extraction Prompt"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Estimate computed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EstimateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Invalid query parameters"
          }
        }
      }
    },
    "/api/v1/extract": {
      "post": {
        "tags": [
          "Extraction"
        ],
        "summary": "Extract structured data from content",
        "description": "Extract structured data from raw HTML, text, or markdown without scraping. Supports multiple extraction pipelines: format conversion (text, json, json_v2, html, markdown, rag), schema-based filtering, LLM extraction via prompt, and profile-based extraction (product, article, job_posting, etc.).\n\n**Cost**: 1 credit per extraction request.",
        "operationId": "extract_content_api_v1_extract_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExtractRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Extraction completed successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "422": {
            "description": "Invalid content or extraction parameters"
          }
        }
      }
    },
    "/api/v1/extract/usage/summary": {
      "get": {
        "tags": [
          "Extraction"
        ],
        "summary": "Aggregate extraction usage totals",
        "description": "Returns period-wide aggregate totals (request count and total billed cost) for the authenticated user's extraction usage. Unlike the paginated /usage endpoint, this endpoint always reflects the full selected period regardless of record count.\n\nPass `hours=N` for recent N hours, or `days=N` for recent N days — but not both. Providing both `hours` and `days` simultaneously returns a 422 error. Omit both to get all-time totals.",
        "operationId": "get_extraction_usage_summary_api_v1_extract_usage_summary_get",
        "parameters": [
          {
            "name": "hours",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 8760,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Hours"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "integer",
                  "maximum": 365,
                  "minimum": 1
                },
                {
                  "type": "null"
                }
              ],
              "title": "Days"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Totals returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionUsageSummaryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation error — hours and days cannot both be provided"
          }
        }
      }
    },
    "/api/v1/extract/usage": {
      "get": {
        "tags": [
          "Extraction"
        ],
        "summary": "List extraction usage history",
        "description": "Returns a paginated list of per-call extraction records for the authenticated user. Records are ordered newest-first. Each record includes provider, model, token counts, AlterLab invocation fee, latency, and success status.\n\nUse `date_from` and `date_to` (ISO 8601, e.g. `2026-05-01`) to filter by date range.",
        "operationId": "list_extraction_usage_api_v1_extract_usage_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Page Size"
            }
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Date From"
            }
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Date To"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage records returned successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExtractionUsageListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Invalid query parameters"
          }
        }
      }
    },
    "/api/v0/scrape": {
      "post": {
        "tags": [
          "Firecrawl Compatible"
        ],
        "summary": "Scrape a URL (Firecrawl-compatible)",
        "description": "Firecrawl-compatible scraping endpoint.\n\nThis endpoint accepts requests in Firecrawl's format and returns responses in Firecrawl's format,\nmaking it easy to migrate from Firecrawl to AlterLab.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/v0/scrape \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"formats\": [\"markdown\", \"html\"]}'\n```\n\n**Migration from Firecrawl:**\nSimply change the base URL from `https://api.firecrawl.dev` to `https://api.alterlab.io`\nand use your AlterLab API key instead of Firecrawl's.",
        "operationId": "firecrawl_scrape_api_v0_scrape_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful scrape",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlScrapeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Scrape failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v0/map": {
      "post": {
        "tags": [
          "Firecrawl Compatible"
        ],
        "summary": "Map a website (Firecrawl-compatible)",
        "description": "Firecrawl-compatible site mapping endpoint.\n\nReturns a list of URLs discovered on the website via sitemap parsing and link extraction.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/v0/map \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"limit\": 100}'\n```",
        "operationId": "firecrawl_map_api_v0_map_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlMapRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlMapResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v0/crawl": {
      "post": {
        "tags": [
          "Firecrawl Compatible"
        ],
        "summary": "Crawl a website (Firecrawl-compatible)",
        "description": "Firecrawl-compatible crawl endpoint. Starts an asynchronous crawl and returns a job ID.\n\nPoll `GET /v0/crawl/{id}` for progress and results.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/v0/crawl \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"limit\": 50, \"maxDepth\": 2}'\n```",
        "operationId": "firecrawl_crawl_api_v0_crawl_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlCrawlRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Crawl started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlCrawlResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v0/crawl/{crawl_id}": {
      "get": {
        "tags": [
          "Firecrawl Compatible"
        ],
        "summary": "Get crawl status (Firecrawl-compatible)",
        "description": "Poll the status of an ongoing or completed crawl.\n\nReturns the current progress, number of pages completed, and scraped data\nwhen the crawl is finished.",
        "operationId": "firecrawl_crawl_status_api_v0_crawl__crawl_id__get",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlCrawlStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Firecrawl Compatible"
        ],
        "summary": "Cancel a crawl (Firecrawl-compatible)",
        "description": "Cancel a running crawl and refund credits for unprocessed pages.",
        "operationId": "firecrawl_cancel_crawl_api_v0_crawl__crawl_id__delete",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl cancelled",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/fc/v1/scrape": {
      "post": {
        "tags": [
          "Firecrawl v1 Compatible"
        ],
        "summary": "Scrape a URL (Firecrawl v1-compatible)",
        "description": "Firecrawl v1-compatible scraping endpoint.\n\nThis endpoint accepts requests in Firecrawl's format and returns responses in Firecrawl's format,\nmaking it easy to migrate from Firecrawl to AlterLab.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/api/fc/v1/scrape \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"formats\": [\"markdown\", \"html\"]}'\n```\n\n**Migration from Firecrawl:**\nSimply change the base URL from `https://api.firecrawl.dev` to `https://api.alterlab.io`\nand use your AlterLab API key instead of Firecrawl's.",
        "operationId": "firecrawl_scrape_api_fc_v1_scrape_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlScrapeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful scrape",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlScrapeResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Scrape failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/fc/v1/map": {
      "post": {
        "tags": [
          "Firecrawl v1 Compatible"
        ],
        "summary": "Map a website (Firecrawl v1-compatible)",
        "description": "Firecrawl v1-compatible site mapping endpoint.\n\nReturns a list of URLs discovered on the website via sitemap parsing and link extraction.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/api/fc/v1/map \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"limit\": 100}'\n```",
        "operationId": "firecrawl_map_api_fc_v1_map_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlMapRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlMapResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/fc/v1/crawl": {
      "post": {
        "tags": [
          "Firecrawl v1 Compatible"
        ],
        "summary": "Crawl a website (Firecrawl v1-compatible)",
        "description": "Firecrawl v1-compatible crawl endpoint. Starts an asynchronous crawl and returns a job ID.\n\nPoll `GET /api/fc/v1/crawl/{id}` for progress and results.\n\n**Authentication:**\n- `Authorization: Bearer <api_key>` (Firecrawl-style)\n- `X-API-Key: <api_key>` (AlterLab-style)\n\n**Example:**\n```bash\ncurl -X POST https://api.alterlab.io/api/fc/v1/crawl \\\n  -H \"Authorization: Bearer sk_live_xxx\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com\", \"limit\": 50, \"maxDepth\": 2}'\n```",
        "operationId": "firecrawl_crawl_api_fc_v1_crawl_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirecrawlCrawlRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Crawl started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlCrawlResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/fc/v1/crawl/{crawl_id}": {
      "get": {
        "tags": [
          "Firecrawl v1 Compatible"
        ],
        "summary": "Get crawl status (Firecrawl v1-compatible)",
        "description": "Poll the status of an ongoing or completed crawl.\n\nReturns the current progress, number of pages completed, and scraped data\nwhen the crawl is finished.",
        "operationId": "firecrawl_crawl_status_api_fc_v1_crawl__crawl_id__get",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlCrawlStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Firecrawl v1 Compatible"
        ],
        "summary": "Cancel a crawl (Firecrawl v1-compatible)",
        "description": "Cancel a running crawl and refund credits for unprocessed pages.",
        "operationId": "firecrawl_cancel_crawl_api_fc_v1_crawl__crawl_id__delete",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl cancelled",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "401": {
            "description": "Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FirecrawlErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{job_id}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Get Job Status",
        "description": "Get job status with authentication and ownership verification.\n\nSecurity:\n- Requires authentication (CurrentUserForPolling dependency)\n- Exempt from pre-auth IP-based rate limit (allows fast polling)\n- Still subject to post-auth per-key rate limiting\n- Verifies job ownership (user_id must match)\n- Returns 404 for non-existent or unauthorized jobs (prevents information disclosure)\n\nRate limiting strategy:\n- Job polling is exempt from the 30 req/min IP-based pre-auth limit\n- This allows users to poll job status without hitting the limit\n  (typical flow: 1 POST scrape + ~5 GET polls = 6 requests per URL)\n- Post-auth per-key limits still apply (tier-based: 100-10000 req/min)\n\nArgs:\n    job_id: UUID of the job\n    user: Current authenticated user (via polling-specific dependency)\n\nReturns:\n    Job status and result\n\nRaises:\n    404: Job not found or doesn't belong to current user",
        "operationId": "get_job_status_api_v1_jobs__job_id__get",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Job Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scrape/light": {
      "post": {
        "tags": [
          "Scraping (Legacy)"
        ],
        "summary": "Scrape (light mode) [DEPRECATED]",
        "description": "**Deprecated**: Use POST /api/v1/scrape with mode='html' instead.",
        "operationId": "scrape_light_api_v1_scrape_light_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeLightRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scrape result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scrape/js": {
      "post": {
        "tags": [
          "Scraping (Legacy)"
        ],
        "summary": "Scrape (JS render mode) [DEPRECATED]",
        "description": "**Deprecated**: Use POST /api/v1/scrape with mode='js' instead.",
        "operationId": "scrape_js_api_v1_scrape_js_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeJSRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scrape result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scrape/pdf": {
      "post": {
        "tags": [
          "Scraping (Legacy)"
        ],
        "summary": "Scrape (PDF mode) [DEPRECATED]",
        "description": "**Deprecated**: Use POST /api/v1/scrape with mode='pdf' instead.",
        "operationId": "scrape_pdf_api_v1_scrape_pdf_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapePDFRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scrape result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/scrape/ocr": {
      "post": {
        "tags": [
          "Scraping (Legacy)"
        ],
        "summary": "Scrape (OCR mode) [DEPRECATED]",
        "description": "**Deprecated**: Use POST /api/v1/scrape with mode='ocr' instead.",
        "operationId": "scrape_ocr_api_v1_scrape_ocr_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeOCRRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Scrape result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs/bulk": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Submit a bulk job batch (B2B enterprise tenants only)",
        "description": "Accepts up to 100,000 job specs in a single push. Jobs are placed into a per-tenant Redis holding set and released into the main worker queue at the contracted throughput rate. Returns immediately after validation — non-blocking.",
        "operationId": "create_bulk_jobs_api_v1_b2b_jobs_bulk_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BulkJobRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "List bulk submissions (B2B enterprise tenants only)",
        "description": "Returns a paginated list of all bulk job submissions for the caller's enterprise organisation, ordered by submission time (newest first).  Use ``limit`` and ``offset`` for pagination.  Maximum page size is 100.",
        "operationId": "list_bulk_jobs_api_v1_b2b_jobs_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Page size (max 100).",
              "default": 20,
              "title": "Limit"
            },
            "description": "Page size (max 100)."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of records to skip.",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of records to skip."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs/bulk/{bulk_id}": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get bulk submission status (B2B enterprise tenants only)",
        "description": "Returns the current status of a bulk job submission including how many jobs have been released from the holding set into the main worker queue.",
        "operationId": "get_bulk_status_api_v1_b2b_jobs_bulk__bulk_id__get",
        "parameters": [
          {
            "name": "bulk_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bulk Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobStatus"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs/bulk/{bulk_id}/results": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get per-item results preview for a bulk submission (B2B enterprise only)",
        "description": "Returns paginated job rows linked to a bulk submission.  Each item includes status, result preview (first 2 KB), error, domain, tier_used, created_at, and completed_at.  Only jobs submitted after migration 0255 (2026-07-02) are included — earlier jobs have no bulk_submission_id FK linkage.  Enterprise guard enforced: 403 if not enterprise.  Tenant isolation enforced: only the caller's own jobs are returned.",
        "operationId": "get_bulk_results_api_v1_b2b_jobs_bulk__bulk_id__results_get",
        "parameters": [
          {
            "name": "bulk_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bulk Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-indexed).",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number (1-indexed)."
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "description": "Number of results per page (max 50).",
              "default": 20,
              "title": "Page Size"
            },
            "description": "Number of results per page (max 50)."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkJobResultsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs/bulk/{bulk_id}/results/download.jsonl": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Download full, untruncated JSONL results for a bulk submission (B2B enterprise only)",
        "description": "Streams every job row linked to a bulk submission as newline-delimited JSON — no pagination cap, no result truncation.  Each line includes query, full ad_results with advertiser details, raw_html_gz, and batchexecute_payloads when present (#28175).  Enterprise guard enforced: 403 if not enterprise.  Tenant isolation enforced: only the caller's own jobs are returned.  409 if the submission is still accepted/draining (#28250).  Response is streamed in batches — safe for bulk submissions with hundreds+ of jobs.  429 if the per-tenant concurrent-download limit is exceeded, or if the download service is temporarily unavailable — see Retry-After.  If the stream runs longer than the server-side wall-clock deadline (B2B_DOWNLOAD_STREAM_TIMEOUT_SECONDS), the response ends early with a final line ``{\"_truncated\": true, \"reason\": \"stream_timeout\"}`` rather than silently cutting off (#28265) — check for this line to detect a partial download.",
        "operationId": "download_bulk_results_jsonl_api_v1_b2b_jobs_bulk__bulk_id__results_download_jsonl_get",
        "parameters": [
          {
            "name": "bulk_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bulk Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response"
          },
          "429": {
            "description": "Per-tenant concurrent-download limit exceeded, or the download service is temporarily unavailable.  Retry-After indicates the recommended wait in seconds."
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/jobs/bulk/{bulk_id}/results/download.csv": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Download a CSV summary of results for a bulk submission (B2B enterprise only)",
        "description": "Streams a CSV summary (query, ad_count, advertiser_names) of every job row linked to a bulk submission — no pagination cap.  Enterprise guard enforced: 403 if not enterprise.  Tenant isolation enforced: only the caller's own jobs are returned.  409 if the submission is still accepted/draining (#28250).  Response is streamed in batches — safe for bulk submissions with hundreds+ of jobs.  429 if the per-tenant concurrent-download limit is exceeded, or if the download service is temporarily unavailable — see Retry-After.  If the stream runs longer than the server-side wall-clock deadline (B2B_DOWNLOAD_STREAM_TIMEOUT_SECONDS), the response ends early with a trailing row ``__truncated__,0,stream_timeout`` rather than silently cutting off (#28265) — check for this sentinel row to detect a partial download.",
        "operationId": "download_bulk_results_csv_api_v1_b2b_jobs_bulk__bulk_id__results_download_csv_get",
        "parameters": [
          {
            "name": "bulk_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Bulk Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response"
          },
          "429": {
            "description": "Per-tenant concurrent-download limit exceeded, or the download service is temporarily unavailable.  Retry-After indicates the recommended wait in seconds."
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/profiles": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Build a demographic browser profile (B2B enterprise tenants only)",
        "description": "Enqueues a YouTube demographic warmup task (~15-18 minutes) that builds a browser profile with a specific age/gender demographic signal.  Poll GET /api/v1/b2b/profiles/{profile_id} until status == 'complete', then use profile_id as session_pool_id in SERP search requests.",
        "operationId": "create_demographic_profile_api_v1_b2b_profiles_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicProfileBuildRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicProfileBuildResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "List demographic profiles for the calling org (B2B enterprise tenants only)",
        "description": "Returns all demographic profiles owned by the calling organisation.  Profiles are stored in Redis with a 48-hour TTL; profiles that have expired no longer appear in this list.  Use the ``status`` query param to filter by build state.  Pagination via ``limit``/``offset`` (default limit: 100, max: 1000).  ``cookie_jar`` is NEVER included in list responses — use GET /api/v1/b2b/profiles/{profile_id} to retrieve the cookie jar for a specific completed profile.",
        "operationId": "list_demographic_profiles_api_v1_b2b_profiles_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "building",
                    "complete",
                    "failed"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional filter by profile build status.  Accepted values: 'building', 'complete', 'failed'.  When omitted, all statuses are returned.",
              "title": "Status"
            },
            "description": "Optional filter by profile build status.  Accepted values: 'building', 'complete', 'failed'.  When omitted, all statuses are returned."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "description": "Maximum number of profiles to return (1–1000).  Default: 100.",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum number of profiles to return (1–1000).  Default: 100."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of profiles to skip before returning results.  Default: 0.",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of profiles to skip before returning results.  Default: 0."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicProfileListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/profiles/{profile_id}": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get demographic profile status (B2B enterprise tenants only)",
        "description": "Returns the current build status of a demographic profile.  When status == 'complete', the response includes cookie_jar and inferred demographics.  Use profile_id as session_pool_id in subsequent SERP search requests to route them through the demographically-targeted session.",
        "operationId": "get_demographic_profile_api_v1_b2b_profiles__profile_id__get",
        "parameters": [
          {
            "name": "profile_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-zA-Z0-9_\\-.]+$",
              "description": "Profile ID returned by POST /api/v1/b2b/profiles.",
              "title": "Profile Id"
            },
            "description": "Profile ID returned by POST /api/v1/b2b/profiles."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicProfileStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/profiles/{profile_id}/stats": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Per-profile ad-performance stats (B2B enterprise tenants only)",
        "description": "Returns aggregated ad-performance metrics for a demographic profile: how many jobs ran through it, how many ads it saw, how many of those were demographically targeted, the demographic-ad rate, when it was last used, and its most recent ads.  Powers the profile-proof dashboard.",
        "operationId": "get_demographic_profile_stats_api_v1_b2b_profiles__profile_id__stats_get",
        "parameters": [
          {
            "name": "profile_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-zA-Z0-9_\\-.]+$",
              "description": "Profile ID returned by POST /api/v1/b2b/profiles.",
              "title": "Profile Id"
            },
            "description": "Profile ID returned by POST /api/v1/b2b/profiles."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfilePerformanceStats"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/profiles/{profile_id}/verify": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Verify demographic inference for a profile (B2B enterprise tenants only)",
        "description": "Enqueues an adssettings.google.com scrape to verify the demographic that Google has inferred for this profile's cookie jar.  Returns 202 immediately — the verification runs asynchronously in the worker.  The result is stored back into the profile state once the worker completes.  Poll GET /api/v1/b2b/profiles/{profile_id} until status == 'complete' to retrieve the verified demographic.",
        "operationId": "verify_demographic_profile_endpoint_api_v1_b2b_profiles__profile_id__verify_post",
        "parameters": [
          {
            "name": "profile_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-zA-Z0-9_\\-.]+$",
              "description": "Profile ID to verify.",
              "title": "Profile Id"
            },
            "description": "Profile ID to verify."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicProfileVerifyRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicProfileVerifyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/delivery-configs": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Create a delivery config (B2B API key — enterprise tenants only)",
        "description": "Create a delivery configuration for the caller's organization via API key.\n\nThe tenant is resolved from the API key — no admin JWT required.\nCredentials are encrypted at rest (AES-256-GCM) and never returned in the response.\nOnly one active config per delivery_type per tenant is allowed (409 if duplicate).\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Credentials encrypted via AES-256-GCM before DB write — never stored in plaintext.\n- Credentials are NOT returned in the response.\n\nSOC 2 CC6.7: create attempt is audit-logged with action='client_create'.",
        "operationId": "create_b2b_delivery_config_api_v1_b2b_tenants__tenant_id__delivery_configs_post",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantDeliveryConfigClientCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "List delivery configs for the caller's org (B2B API key)",
        "description": "List delivery configurations for the caller's enterprise organization.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Credentials are NEVER returned (excluded by TenantDeliveryConfigResponse schema).\n\nSOC 2 CC6.7: read access is audit-logged with actor and request context.",
        "operationId": "list_b2b_delivery_configs_api_v1_b2b_tenants__tenant_id__delivery_configs_get",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include inactive configs (default: active only)",
              "default": false,
              "title": "Include Inactive"
            },
            "description": "Include inactive configs (default: active only)"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "description": "Maximum number of configs to return",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum number of configs to return"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of configs to skip (for pagination)",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of configs to skip (for pagination)"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/delivery-configs/{config_id}": {
      "patch": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Update non-credential fields of a delivery config (B2B API key)",
        "description": "Update non-credential fields of the caller's delivery configuration.\n\nModifies only config_json, freshness_target_seconds, retry_policy_json, and\nis_active.  To replace credentials use the /rotate endpoint.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Credentials are NOT accepted or modified by this endpoint.\n\nSOC 2 CC6.7: every update is audit-logged with action='client_update' and request context.",
        "operationId": "update_b2b_delivery_config_api_v1_b2b_tenants__tenant_id__delivery_configs__config_id__patch",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Delivery config UUID",
              "title": "Config Id"
            },
            "description": "Delivery config UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantDeliveryConfigUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get a specific delivery config for the caller's org (B2B API key)",
        "description": "Get a specific delivery configuration for the caller's enterprise organization.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Credentials are NEVER returned (excluded by TenantDeliveryConfigResponse schema).\n\nSOC 2 CC6.7: read access is audit-logged with actor, config_id, and request context.",
        "operationId": "get_b2b_delivery_config_api_v1_b2b_tenants__tenant_id__delivery_configs__config_id__get",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Delivery config UUID",
              "title": "Config Id"
            },
            "description": "Delivery config UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/delivery-configs/{config_id}/rotate": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Rotate (replace) delivery credentials without downtime (B2B API key)",
        "description": "Replace delivery credentials in-place without downtime.\n\nNew credentials are encrypted with a fresh AES-256-GCM nonce.\nOld credentials are permanently replaced — they cannot be recovered.\nNew credentials are NOT returned in the response.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Credentials are encrypted at rest immediately; old credentials are wiped.\n- Credentials are NEVER returned in any response.\n\nSOC 2 CC6.7: credential rotation is audit-logged with action='client_rotate_credentials'\nto distinguish client self-service rotations from admin-initiated rotations.",
        "operationId": "rotate_b2b_delivery_credentials_api_v1_b2b_tenants__tenant_id__delivery_configs__config_id__rotate_post",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Delivery config UUID",
              "title": "Config Id"
            },
            "description": "Delivery config UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantDeliveryConfigRotateCredentials"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/delivery-configs/{config_id}/trigger": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Trigger a manual delivery run (B2B API key — integration testing)",
        "description": "Manually trigger a delivery run via API key auth (no admin Bearer JWT required).\n\nIntended for integration testing and pilot validation (Marcode TEST 8).\nNOT a production delivery pathway — result count is capped at 1000 by the schema.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Config CRUD and credential management remain admin-only at\n  /api/v1/admin/tenants/…/delivery-configs/.\n\nSOC 2 CC6.7: trigger attempt is audit-logged regardless of outcome.",
        "operationId": "trigger_b2b_delivery_api_v1_b2b_tenants__tenant_id__delivery_configs__config_id__trigger_post",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Delivery config UUID",
              "title": "Config Id"
            },
            "description": "Delivery config UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantDeliveryTriggerRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryTriggerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/delivery-configs/{config_id}/test": {
      "post": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Test a delivery config connection (B2B API key — enterprise tenants only)",
        "description": "Test a delivery configuration connection via API key auth.\n\nDecrypts credentials and performs a live connectivity check:\n  - s3: uploads and deletes a small test object; returns success/failure with message\n  - webhook: verifies credentials are decryptable (no URL ping — SSRF fires on real\n    delivery; this confirms the stored secret can be retrieved correctly)\n  - polling / batch_export: verifies credential decrypt succeeds\n\nCredentials are NEVER returned or logged.\n\nSecurity:\n- tenant_id in the path must match the caller's org (resolved from API key).\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Enterprise guard: account_type must be 'enterprise'.\n- Only active configs may be tested (400 if is_active=False).\n\nSOC 2 CC6.7: all test-connection calls are audit-logged with action=client_test_connection.",
        "operationId": "test_b2b_delivery_config_api_v1_b2b_tenants__tenant_id__delivery_configs__config_id__test_post",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "config_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Delivery config UUID",
              "title": "Config Id"
            },
            "description": "Delivery config UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDeliveryConfigTestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/proxy/feedback": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Poll BYOP proxy outcome feedback (enterprise only)",
        "description": "Return and clear per-request SERP outcome events for BYOP proxy management.\n\nMarcode's proxy manager needs to know whether each SERP request succeeded\nor was blocked by Google so it can rotate IPs and waterfall to more\nexpensive proxies on their side (#23892, #23894).\n\nEvents are pushed to Redis by the worker after each SERP search and popped\natomically here.\n\nEvent fields:\n- ``job_id``          — SERP job identifier for correlation.\n- ``query``           — Search query (truncated to 100 chars).\n- ``status``          — ``\"success\"`` | ``\"blocked\"`` | ``\"failed\"``.\n- ``block_reason``    — Narrows the block type (``null`` on success or when\n                        signal is unavailable).  Values:\n                        ``\"search_guard\"`` — Google search-guard / consent\n                        interstitial (SerpBlockedError from engine).\n                        ``\"rate_limited\"`` — HTTP 429 or rate-limit body.\n                        ``\"no_results\"`` — other block (engine returned errors\n                        but no matching 429/guard signal).\n                        ``\"timeout\"`` / ``\"error\"`` — set by caller on the\n                        exception path before a result could be obtained.\n                        ``null`` — parallel-engine path (insufficient signal).\n- ``country``         — Requested ISO 3166-1 alpha-2 geo (e.g. ``\"GB\"``).\n                        Use for per-country waterfall routing.  ``null`` when\n                        no explicit geo was requested.\n- ``session_pool_id`` — Demographic profile pool id (e.g. persona UUID) for\n                        this request.  ``null`` for non-demographic requests.\n- ``ts``              — ISO 8601 UTC timestamp.\n\nStatus values:\n- ``\"success\"`` — at least one organic result was returned (proxy worked).\n- ``\"blocked\"`` — Google returned zero organic results for the request.\n- ``\"failed\"``  — network or timeout error (not a Google-level block).\n\nThis endpoint is idempotent in the following sense: once events are popped\nthey are gone — the caller must process them before the next call.  The\nRedis list has a 24-hour TTL; unpolled events auto-expire.\n\nArgs:\n    limit: Maximum number of events to return (1–1000, default 100).\n\nReturns:\n    ``{\"events\": [...], \"count\": N}``",
        "operationId": "get_byop_proxy_feedback_api_v1_b2b_proxy_feedback_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "description": "Maximum number of events to return (1–1000, default 100).",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum number of events to return (1–1000, default 100)."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ByopFeedbackResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/deliveries": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get delivery history (B2B enterprise tenants only)",
        "description": "Returns paginated delivery receipts for the caller's organization. Receipts are ordered newest-first. Use ``status`` to filter by outcome ('success' or 'failure'). Use ``delivery_type`` to filter by delivery method ('s3', 'webhook', 'polling', 'batch_export'). Only enterprise accounts may access this endpoint (403 otherwise).",
        "operationId": "get_delivery_history_api_v1_b2b_deliveries_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "description": "Page size — number of receipts to return (1–200, default 50).",
              "default": 50,
              "title": "Limit"
            },
            "description": "Page size — number of receipts to return (1–200, default 50)."
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "0-based row offset for pagination (default 0).",
              "default": 0,
              "title": "Offset"
            },
            "description": "0-based row offset for pagination (default 0)."
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "success",
                    "failure"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional filter by delivery outcome. Accepted values: 'success', 'failure'. When omitted, all statuses are returned.",
              "title": "Status"
            },
            "description": "Optional filter by delivery outcome. Accepted values: 'success', 'failure'. When omitted, all statuses are returned."
          },
          {
            "name": "delivery_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "enum": [
                    "s3",
                    "webhook",
                    "polling",
                    "batch_export"
                  ],
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Optional filter by delivery method. Accepted values: 's3', 'webhook', 'polling', 'batch_export'. When omitted, all delivery types are returned.",
              "title": "Delivery Type"
            },
            "description": "Optional filter by delivery method. Accepted values: 's3', 'webhook', 'polling', 'batch_export'. When omitted, all delivery types are returned."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryHistoryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/notification-prefs": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Get notification preferences (enterprise tenant self-service)",
        "description": "Return all notification preferences for the calling enterprise tenant (#25995).\n\nScoped to the caller's own organization — no cross-tenant access is possible.\nReturns an empty prefs list if no rows have been seeded yet (not an error).\n\nAuthentication: enterprise API key with b2b:read scope.",
        "operationId": "get_b2b_notification_prefs_api_v1_b2b_notification_prefs_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationPrefListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Update notification preferences (enterprise tenant self-service)",
        "description": "Upsert notification preferences for the calling enterprise tenant (#25995).\n\nEach item in the request body is upserted via INSERT ... ON CONFLICT DO UPDATE.\nRows not mentioned in the request are left unchanged.\ntenant_id is always sourced from the caller's authenticated org — the request\nbody does NOT accept a tenant_id (IDOR prevention).\n\nReturns the full list of preferences for the tenant after the upsert.\n\nAuthentication: enterprise API key with b2b:write scope.",
        "operationId": "update_b2b_notification_prefs_api_v1_b2b_notification_prefs_patch",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NotificationPrefPatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationPrefPatchResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/tenants/{tenant_id}/config": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "Read tenant config (B2B API key — enterprise only)",
        "description": "Return the public read view of the caller's tenant configuration.\n\nShows: rate shape (jobs/hour, burst limit via concurrent_requests),\nS3 delivery bucket name and region (no credentials), session country\ndefault, MFA and audit settings.\n\nSecurity:\n- Enterprise guard: account_type must be 'enterprise'.\n- Tenant isolation: tenant_id in the path must match the caller's org.\n  Mismatches are collapsed to 404 to prevent IDOR oracles.\n- Credential fields (byop_proxy_url, webhook_url, sso_config, custom_pricing)\n  are excluded from the response schema — they never leave this function.",
        "operationId": "get_b2b_tenant_config_api_v1_b2b_tenants__tenant_id__config_get",
        "parameters": [
          {
            "name": "tenant_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization (tenant) UUID",
              "title": "Tenant Id"
            },
            "description": "Organization (tenant) UUID"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantConfigReadResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/health": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "B2B org-scoped health aggregator",
        "description": "Returns aggregated SLA metrics for the calling enterprise org: ad fill rate, SERP success rate, delivery success rate, and batch counts. All metrics are scoped to the authenticated org — no cross-tenant data. Individual metrics return ``null`` when the underlying data source is unavailable. Responses are cached for 30 seconds to absorb polling load.",
        "operationId": "get_b2b_health_api_v1_b2b_health_get",
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "required": false,
            "schema": {
              "enum": [
                "24h",
                "7d",
                "30d"
              ],
              "type": "string",
              "description": "Aggregation window: '24h' (last 24 hours), '7d' (last 7 days), '30d' (last 30 days).",
              "default": "24h",
              "title": "Window"
            },
            "description": "Aggregation window: '24h' (last 24 hours), '7d' (last 7 days), '30d' (last 30 days)."
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/B2BHealthResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/b2b/usage": {
      "get": {
        "tags": [
          "B2B Intake"
        ],
        "summary": "B2B org-scoped billing-period usage aggregator",
        "description": "Returns aggregated usage metrics for the calling enterprise org's current billing period: queries used/limit, ad fill rate, average ads per query, demographic ad rate, and bulk job counts. All metrics are scoped to the authenticated org — no cross-tenant data. Ad/demographic metrics return `null` when the underlying Redis data is unavailable. Responses are cached for 30 seconds to absorb polling load.",
        "operationId": "get_b2b_usage_api_v1_b2b_usage_get",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/B2BUsageResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch": {
      "post": {
        "tags": [
          "Batch"
        ],
        "summary": "Submit a batch scrape",
        "description": "Submit up to 100 URLs for parallel scraping. Credits are pre-debited based on estimated tier costs; unused credits are refunded per-job as results arrive. Returns immediately with a `batch_id` for polling via `GET /v1/scrape/batch/{batch_id}`.\n\n**Cost**: 1–20 credits per URL depending on tier used. Supports webhook notification on batch completion.",
        "operationId": "create_batch_api_v1_batch_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Batch accepted — poll for status or await webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URLs, empty batch, or SSRF violation"
          },
          "402": {
            "description": "Insufficient credits for estimated batch cost"
          },
          "422": {
            "description": "Invalid request parameters"
          }
        }
      }
    },
    "/api/v1/batch/{batch_id}": {
      "get": {
        "tags": [
          "Batch"
        ],
        "summary": "Poll batch status",
        "description": "Get the current status, progress, and per-job results of a batch scrape. Returns aggregated counts (completed, failed, pending) and individual job results as they finish.",
        "operationId": "get_batch_status_api_v1_batch__batch_id__get",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Batch Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch status returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Batch not found or expired (2h TTL)"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/{batch_id}/stream": {
      "get": {
        "tags": [
          "Batch"
        ],
        "summary": "Stream batch progress (SSE)",
        "description": "Stream real-time batch progress via Server-Sent Events. Emits `progress` events as jobs complete and a `complete` event when the batch finishes. Supports `Last-Event-Id` for reconnection.",
        "operationId": "stream_batch_progress_api_v1_batch__batch_id__stream_get",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Batch Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/{batch_id}/webhook-log": {
      "get": {
        "tags": [
          "Batch"
        ],
        "summary": "Get batch webhook delivery log",
        "description": "Retrieve all webhook delivery attempts for a batch, including status codes, errors, and timestamps.",
        "operationId": "get_batch_webhook_log_api_v1_batch__batch_id__webhook_log_get",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Batch Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook log returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryLog"
                }
              }
            }
          },
          "404": {
            "description": "Batch not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batch/{batch_id}/webhook-retry": {
      "post": {
        "tags": [
          "Batch"
        ],
        "summary": "Retry a failed batch webhook",
        "description": "Manually retry a failed or cancelled webhook delivery. Resets the webhook status and fires a new delivery attempt with retries.",
        "operationId": "retry_batch_webhook_api_v1_batch__batch_id__webhook_retry_post",
        "parameters": [
          {
            "name": "batch_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Batch Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook retry initiated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryLog"
                }
              }
            }
          },
          "400": {
            "description": "No webhook URL configured or webhook already succeeded"
          },
          "404": {
            "description": "Batch not found"
          },
          "409": {
            "description": "Webhook delivery already in progress"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batches": {
      "get": {
        "tags": [
          "Batch"
        ],
        "summary": "List batches",
        "description": "Return a paginated list of the authenticated user's batch scrapes, ordered by most recent first. Aggregates per-batch job counts and status.",
        "operationId": "list_batches_api_v1_batches_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "description": "Maximum batches per page (1-50)",
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum batches per page (1-50)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of batches to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of batches to skip"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated batch list with per-batch summaries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/batches/analytics": {
      "get": {
        "tags": [
          "Batch"
        ],
        "summary": "Get batch analytics",
        "description": "Aggregate analytics for the user's batch scraping activity over a given time window. Returns summary stats, daily trends, domain breakdown, and tier distribution.",
        "operationId": "get_batch_analytics_api_v1_batches_analytics_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "description": "Number of days to look back",
              "default": 30,
              "title": "Days"
            },
            "description": "Number of days to look back"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch analytics with trends and breakdowns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules": {
      "post": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Create Crawl Schedule",
        "description": "Create a new crawl schedule.",
        "operationId": "create_crawl_schedule_api_v1_crawl_schedules_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlScheduleCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "List Crawl Schedules",
        "description": "List user's crawl schedules.",
        "operationId": "list_crawl_schedules_api_v1_crawl_schedules_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Active Only"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules/{schedule_id}": {
      "get": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Get Crawl Schedule",
        "description": "Get crawl schedule details.",
        "operationId": "get_crawl_schedule_api_v1_crawl_schedules__schedule_id__get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Update Crawl Schedule",
        "description": "Update a crawl schedule. Recomputes next_run_at if cron or timezone changes.",
        "operationId": "update_crawl_schedule_api_v1_crawl_schedules__schedule_id__patch",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlScheduleUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Delete Crawl Schedule",
        "description": "Soft-delete a crawl schedule.",
        "operationId": "delete_crawl_schedule_api_v1_crawl_schedules__schedule_id__delete",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules/{schedule_id}/pause": {
      "post": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Pause Crawl Schedule",
        "description": "Pause a crawl schedule.",
        "operationId": "pause_crawl_schedule_api_v1_crawl_schedules__schedule_id__pause_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules/{schedule_id}/resume": {
      "post": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Resume Crawl Schedule",
        "description": "Resume a paused crawl schedule. Recomputes next_run_at.",
        "operationId": "resume_crawl_schedule_api_v1_crawl_schedules__schedule_id__resume_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules/{schedule_id}/runs": {
      "get": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "List Crawl Schedule Runs",
        "description": "Get execution history for a crawl schedule.",
        "operationId": "list_crawl_schedule_runs_api_v1_crawl_schedules__schedule_id__runs_get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleRunListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/schedules/{schedule_id}/run": {
      "post": {
        "tags": [
          "Crawl Schedules"
        ],
        "summary": "Run Crawl Schedule Now",
        "description": "Manually trigger an immediate crawl run for a schedule.\n\nExecutes the crawl outside its cron cadence.  next_run_at is NOT\nadvanced so the regular schedule is unaffected by the manual trigger.\nWorks for both active and paused schedules.",
        "operationId": "run_crawl_schedule_now_api_v1_crawl_schedules__schedule_id__run_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlScheduleRunResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl": {
      "post": {
        "tags": [
          "Crawl"
        ],
        "summary": "Start a website crawl",
        "description": "Discover pages on a website via sitemap parsing and link extraction, then scrape them. Returns immediately with a crawl_id for polling. Supports depth crawling, URL pattern filtering, priority scoring, cost controls, change tracking, output connectors (S3/GCS/webhook), caching, custom headers, and webhook notifications.",
        "operationId": "create_crawl_api_v1_crawl_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Crawl accepted and discovery started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL, conflicting parameters, or SSRF violation"
          },
          "402": {
            "description": "Insufficient credits for estimated crawl cost"
          },
          "429": {
            "description": "Concurrent crawl slot limit reached for your balance tier"
          },
          "503": {
            "description": "Queue full — too many jobs queued system-wide"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Crawl"
        ],
        "summary": "List crawls",
        "description": "Return a paginated list of the authenticated user's crawls. Merges in-progress crawls from Redis with completed crawls from the crawl_history table. Supports filtering by status, domain substring, and date range.",
        "operationId": "list_crawls_api_v1_crawl_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Max items to return",
              "default": 20,
              "title": "Limit"
            },
            "description": "Max items to return"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of items to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of items to skip"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by crawl status (discovering, scraping, completed, partial, failed, cancelled)",
              "title": "Status"
            },
            "description": "Filter by crawl status (discovering, scraping, completed, partial, failed, cancelled)"
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by domain substring (case-insensitive)",
              "title": "Domain"
            },
            "description": "Filter by domain substring (case-insensitive)"
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter: created_at >= this ISO date (YYYY-MM-DD)",
              "title": "Date From"
            },
            "description": "Filter: created_at >= this ISO date (YYYY-MM-DD)"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter: created_at <= this ISO date (YYYY-MM-DD)",
              "title": "Date To"
            },
            "description": "Filter: created_at <= this ISO date (YYYY-MM-DD)"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(created_at|status)$",
              "description": "Sort field (created_at or status)",
              "default": "created_at",
              "title": "Sort"
            },
            "description": "Sort field (created_at or status)"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(asc|desc)$",
              "description": "Sort order (asc or desc)",
              "default": "desc",
              "title": "Order"
            },
            "description": "Sort order (asc or desc)"
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/{crawl_id}": {
      "get": {
        "tags": [
          "Crawl"
        ],
        "summary": "Poll crawl status and results",
        "description": "Get the current status, progress, billing breakdown, and optionally per-page results of a crawl. Supports pagination (offset/limit) for large crawls and optional depth statistics. On completion, triggers automatic overpayment refund.",
        "operationId": "get_crawl_status_api_v1_crawl__crawl_id__get",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "include_results",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include per-page results",
              "default": false,
              "title": "Include Results"
            },
            "description": "Include per-page results"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl status with optional page results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlStatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found or expired (2h TTL)"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Crawl"
        ],
        "summary": "Cancel a crawl and refund credits",
        "description": "Cancel an active crawl. Pending and queued jobs are cancelled, and credits for unprocessed pages are automatically refunded. Already completed or in-progress jobs are not affected.",
        "operationId": "cancel_crawl_api_v1_crawl__crawl_id__delete",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl cancelled with refund summary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlCancelResponse"
                }
              }
            }
          },
          "404": {
            "description": "Crawl not found or expired"
          },
          "409": {
            "description": "Crawl already completed or cancelled"
          },
          "500": {
            "description": "CAS write exhausted — refund applied, retry cancel to persist status"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/{crawl_id}/export": {
      "get": {
        "tags": [
          "Crawl"
        ],
        "summary": "Export crawl results",
        "description": "Download all crawl page results as a file. Supports CSV, JSON, and JSONL formats. Optionally filter by page status or select specific fields. Returns 404 if the crawl is not found or has expired (2h TTL).",
        "operationId": "export_crawl_api_v1_crawl__crawl_id__export_get",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(json|jsonl|csv)$",
              "description": "Output format: json (array), jsonl (newline-delimited), or csv",
              "default": "json",
              "title": "Format"
            },
            "description": "Output format: json (array), jsonl (newline-delimited), or csv"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "pattern": "^(succeeded|failed|rejected|expired|queued|processing|cancelled|all)$"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter pages by status. Use 'all' to include every page regardless of status. Valid statuses: succeeded, failed, rejected, expired, queued, processing, cancelled, all.",
              "default": "succeeded",
              "title": "Status"
            },
            "description": "Filter pages by status. Use 'all' to include every page regardless of status. Valid statuses: succeeded, failed, rejected, expired, queued, processing, cancelled, all."
          },
          {
            "name": "fields",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Comma-separated list of fields to include in output (e.g. 'url,html,status'). Omit to include all fields.",
              "title": "Fields"
            },
            "description": "Comma-separated list of fields to include in output (e.g. 'url,html,status'). Omit to include all fields."
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Crawl results file download",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "404": {
            "description": "Crawl not found or expired"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/{crawl_id}/stream": {
      "get": {
        "tags": [
          "Crawl"
        ],
        "summary": "Stream Crawl",
        "description": "Stream crawl events in real-time via Server-Sent Events.\n\nSubscribes to the Redis Pub/Sub channel ``crawl:{crawl_id}:events``\nand forwards events to the client as they arrive.  This provides\ninstant page results without polling — critical for AI agent workflows\nthat process pages as they complete.\n\n**Event types**:\n\n- ``page.completed`` — A page was successfully scraped.\n- ``page.failed`` — A page scrape failed.\n- ``crawl.progress`` — Periodic progress summary.\n- ``crawl.completed`` — Crawl finished (connection closes after this).\n- ``heartbeat`` — Keep-alive ping (every 15 s).\n- ``timeout`` — Connection duration limit reached; reconnect to resume.\n\nThe stream auto-closes when the crawl completes, the client\ndisconnects, or the maximum connection duration (30 min) is reached.\nClients can reconnect using the ``Last-Event-ID`` header to avoid\nduplicate processing on their side (event IDs are monotonically\nincreasing integers).\n\n**Usage**::\n\n    curl -N -H \"X-API-Key: sk_live_...\" \\\n        http://localhost/api/v1/crawl/{crawl_id}/stream\n\nRequires: read scope (via API key)",
        "operationId": "stream_crawl_api_v1_crawl__crawl_id__stream_get",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crawl/{crawl_id}/resume": {
      "post": {
        "tags": [
          "Crawl"
        ],
        "summary": "Resume a cancelled or failed crawl",
        "description": "Re-enqueue failed and/or cancelled jobs from a previous crawl without re-crawling pages that already succeeded. Optionally add new URLs. Credits are debited only for newly enqueued work.",
        "operationId": "resume_crawl_api_v1_crawl__crawl_id__resume_post",
        "parameters": [
          {
            "name": "crawl_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Crawl Id"
            }
          },
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CrawlResumeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Crawl resumed with re-enqueued jobs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CrawlResumeResponse"
                }
              }
            }
          },
          "400": {
            "description": "No retryable jobs found"
          },
          "402": {
            "description": "Insufficient credits for resumed work"
          },
          "404": {
            "description": "Crawl not found or expired"
          },
          "409": {
            "description": "Crawl is still actively scraping or resume already in progress"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules": {
      "post": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Create Map Schedule",
        "description": "Create a new map schedule.",
        "operationId": "create_map_schedule_api_v1_map_schedules_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MapScheduleCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "List Map Schedules",
        "description": "List user's map schedules.",
        "operationId": "list_map_schedules_api_v1_map_schedules_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Active Only"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules/{schedule_id}": {
      "get": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Get Map Schedule",
        "description": "Get map schedule details.",
        "operationId": "get_map_schedule_api_v1_map_schedules__schedule_id__get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Update Map Schedule",
        "description": "Update a map schedule. Recomputes next_run_at if cron or timezone changes.",
        "operationId": "update_map_schedule_api_v1_map_schedules__schedule_id__patch",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MapScheduleUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Delete Map Schedule",
        "description": "Soft-delete a map schedule.",
        "operationId": "delete_map_schedule_api_v1_map_schedules__schedule_id__delete",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules/{schedule_id}/pause": {
      "post": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Pause Map Schedule",
        "description": "Pause a map schedule.",
        "operationId": "pause_map_schedule_api_v1_map_schedules__schedule_id__pause_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules/{schedule_id}/resume": {
      "post": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Resume Map Schedule",
        "description": "Resume a paused map schedule. Recomputes next_run_at.",
        "operationId": "resume_map_schedule_api_v1_map_schedules__schedule_id__resume_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules/{schedule_id}/runs": {
      "get": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "List Map Schedule Runs",
        "description": "Get execution history for a map schedule.",
        "operationId": "list_map_schedule_runs_api_v1_map_schedules__schedule_id__runs_get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleRunListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/schedules/{schedule_id}/run": {
      "post": {
        "tags": [
          "Map Schedules"
        ],
        "summary": "Run Map Schedule Now",
        "description": "Manually trigger an immediate map run for a schedule.\n\nExecutes the map outside its cron cadence. next_run_at is NOT\nadvanced so the regular schedule is unaffected by the manual trigger.\nWorks for both active and paused schedules.",
        "operationId": "run_map_schedule_now_api_v1_map_schedules__schedule_id__run_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapScheduleRunResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map": {
      "post": {
        "tags": [
          "Map"
        ],
        "summary": "Discover site structure",
        "description": "Discover all URLs on a website via sitemap parsing and link extraction. No JS rendering, no content scraping — pure lightweight discovery. Supports pattern filtering, search ranking, metadata enrichment, and subdomain inclusion. Costs 1 credit per call regardless of URL count.",
        "operationId": "create_map_api_v1_map_post",
        "parameters": [
          {
            "name": "skip_pre_auth_rate_limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Skip Pre Auth Rate Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MapRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Discovered URLs with metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or conflicting parameters"
          },
          "402": {
            "description": "Insufficient credits (need at least 1)"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Map"
        ],
        "summary": "List map history",
        "description": "List the authenticated user's past map operations, newest first. Supports limit/offset pagination and optional domain filtering.",
        "operationId": "list_maps_api_v1_map_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Maximum items to return",
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum items to return"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of items to skip",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of items to skip"
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by domain",
              "title": "Domain"
            },
            "description": "Filter by domain"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of map history entries",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/compare": {
      "get": {
        "tags": [
          "Map"
        ],
        "summary": "Compare two map snapshots",
        "description": "Compare two maps of the same domain to detect structural changes. Returns added, removed, and unchanged URLs between the two snapshots. Both maps must belong to the requesting user and share the same domain. URL lists are paginated per category — use limit/offset to page through each.",
        "operationId": "compare_maps_api_v1_map_compare_get",
        "parameters": [
          {
            "name": "map_id_a",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Baseline map ID (older snapshot)",
              "title": "Map Id A"
            },
            "description": "Baseline map ID (older snapshot)"
          },
          {
            "name": "map_id_b",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Comparison map ID (newer snapshot)",
              "title": "Map Id B"
            },
            "description": "Comparison map ID (newer snapshot)"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 1000,
              "minimum": 1,
              "description": "Maximum URL entries to return per category (added/removed/changed/unchanged)",
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum URL entries to return per category (added/removed/changed/unchanged)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of entries to skip per category",
              "default": 0,
              "title": "Offset"
            },
            "description": "Number of entries to skip per category"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Comparison result with added/removed/unchanged URLs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapComparisonResponse"
                }
              }
            }
          },
          "400": {
            "description": "Maps belong to different domains"
          },
          "404": {
            "description": "One or both map IDs not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/{map_id}": {
      "get": {
        "tags": [
          "Map"
        ],
        "summary": "Retrieve a past map result",
        "description": "Retrieve the full result of a past map operation including all discovered URLs with metadata. Only the owner can access their maps.",
        "operationId": "get_map_api_v1_map__map_id__get",
        "parameters": [
          {
            "name": "map_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Map Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full map result with discovered URLs",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MapDetailResponse"
                }
              }
            }
          },
          "404": {
            "description": "Map not found or not owned by user"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/map/{map_id}/export": {
      "get": {
        "tags": [
          "Map"
        ],
        "summary": "Export map results",
        "description": "Download a past map result as CSV, JSON, or Sitemap XML. Generates the file server-side and streams the response with appropriate Content-Type headers for direct download.",
        "operationId": "export_map_api_v1_map__map_id__export_get",
        "parameters": [
          {
            "name": "map_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Map Id"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(csv|json|xml)$",
              "description": "Export format: csv, json, or xml (Sitemap XML)",
              "default": "json",
              "title": "Format"
            },
            "description": "Export format: csv, json, or xml (Sitemap XML)"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "File download (CSV, JSON, or XML)",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "404": {
            "description": "Map not found or not owned by user"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules": {
      "post": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Create a search schedule",
        "description": "Create a recurring SERP search schedule using a cron expression. Each run executes a keyword search and records the results. Schedule limits depend on your credit balance tier.",
        "operationId": "create_search_schedule_api_v1_search_schedules_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchScheduleCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Search schedule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleResponse"
                }
              }
            }
          },
          "403": {
            "description": "Schedule limit reached for your balance tier"
          },
          "422": {
            "description": "Invalid cron expression or minimum interval violated"
          }
        }
      },
      "get": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "List search schedules",
        "description": "List user's search schedules.",
        "operationId": "list_search_schedules_api_v1_search_schedules_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Active Only"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules/{schedule_id}": {
      "get": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Get search schedule details",
        "description": "Get search schedule details.",
        "operationId": "get_search_schedule_api_v1_search_schedules__schedule_id__get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Update a search schedule",
        "description": "Update a search schedule. Recomputes next_run_at if cron or timezone changes.",
        "operationId": "update_search_schedule_api_v1_search_schedules__schedule_id__patch",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchScheduleUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Delete a search schedule",
        "description": "Soft-delete a search schedule.",
        "operationId": "delete_search_schedule_api_v1_search_schedules__schedule_id__delete",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules/{schedule_id}/pause": {
      "post": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Pause a search schedule",
        "description": "Pause a search schedule.",
        "operationId": "pause_search_schedule_api_v1_search_schedules__schedule_id__pause_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules/{schedule_id}/resume": {
      "post": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Resume a paused search schedule",
        "description": "Resume a paused search schedule. Recomputes next_run_at.",
        "operationId": "resume_search_schedule_api_v1_search_schedules__schedule_id__resume_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules/{schedule_id}/runs": {
      "get": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "List search schedule run history",
        "description": "Get execution history for a search schedule.",
        "operationId": "list_search_schedule_runs_api_v1_search_schedules__schedule_id__runs_get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleRunListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/search/schedules/{schedule_id}/run": {
      "post": {
        "tags": [
          "Search Schedules"
        ],
        "summary": "Manually trigger a search schedule run",
        "description": "Manually trigger an immediate search run for a schedule.\n\nExecutes the search outside its cron cadence. next_run_at is NOT\nadvanced so the regular schedule is unaffected by the manual trigger.\nWorks for both active and paused schedules.\n\nRate-limited to 5 manual triggers per user per minute to prevent\nworker exhaustion from the inline 30-second SERP wait.",
        "operationId": "run_search_schedule_now_api_v1_search_schedules__schedule_id__run_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchScheduleRunResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded — at most 5 manual triggers per minute"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Create a schedule",
        "description": "Create a recurring scrape schedule using a cron expression. The scheduler automatically triggers scrape jobs at the specified times. Schedule limits depend on your credit balance tier.",
        "operationId": "create_schedule_api_v1_schedules_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Schedule created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid cron expression or minimum interval violated"
          },
          "402": {
            "description": "Insufficient balance for this schedule tier"
          },
          "409": {
            "description": "Schedule limit reached for your balance tier"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "List schedules",
        "description": "Return a paginated list of your scrape schedules. Optionally filter to active-only schedules.",
        "operationId": "list_schedules_api_v1_schedules_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Active Only"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of schedules",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/analytics": {
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "Get schedule analytics",
        "description": "Aggregate analytics across all your schedules: summary stats, per-schedule health rankings, and credit forecast.",
        "operationId": "get_schedule_analytics_api_v1_schedules_analytics_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule analytics with health rankings and forecasts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/{schedule_id}": {
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "Get schedule details",
        "description": "Get a single schedule's configuration, status, and next run time.",
        "operationId": "get_schedule_api_v1_schedules__schedule_id__get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Schedules"
        ],
        "summary": "Update a schedule",
        "description": "Update a schedule's configuration. Recomputes the next run time if cron expression or timezone changes.",
        "operationId": "update_schedule_api_v1_schedules__schedule_id__patch",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Schedule updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid cron expression"
          },
          "404": {
            "description": "Schedule not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Schedules"
        ],
        "summary": "Delete a schedule",
        "description": "Soft-delete a schedule. It will no longer trigger.",
        "operationId": "delete_schedule_api_v1_schedules__schedule_id__delete",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Schedule deleted"
          },
          "404": {
            "description": "Schedule not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/{schedule_id}/pause": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Pause a schedule",
        "description": "Pause a schedule so it stops triggering until resumed.",
        "operationId": "pause_schedule_api_v1_schedules__schedule_id__pause_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule paused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found"
          },
          "409": {
            "description": "Schedule already paused"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/{schedule_id}/resume": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Resume a schedule",
        "description": "Resume a paused schedule. Recomputes the next run time.",
        "operationId": "resume_schedule_api_v1_schedules__schedule_id__resume_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule resumed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleResponse"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found"
          },
          "409": {
            "description": "Schedule is not paused"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/{schedule_id}/run": {
      "post": {
        "tags": [
          "Schedules"
        ],
        "summary": "Trigger a schedule now",
        "description": "Manually trigger a schedule execution immediately, outside its cron schedule. Credits are debited normally.",
        "operationId": "run_schedule_now_api_v1_schedules__schedule_id__run_post",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Schedule triggered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleRunResponse"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits"
          },
          "404": {
            "description": "Schedule not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/schedules/{schedule_id}/runs": {
      "get": {
        "tags": [
          "Schedules"
        ],
        "summary": "List schedule runs",
        "description": "Return a paginated history of a schedule's execution runs, most recent first.",
        "operationId": "list_schedule_runs_api_v1_schedules__schedule_id__runs_get",
        "parameters": [
          {
            "name": "schedule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Schedule Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Run history returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScheduleRunListResponse"
                }
              }
            }
          },
          "404": {
            "description": "Schedule not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "List Alert Rules",
        "description": "List all alert rules for the current organization.",
        "operationId": "list_alert_rules_api_v1_alerts_rules_get",
        "parameters": [
          {
            "name": "alert_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AlertType"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by alert type",
              "title": "Alert Type"
            },
            "description": "Filter by alert type"
          },
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include disabled rules",
              "default": false,
              "title": "Include Inactive"
            },
            "description": "Include disabled rules"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Alerts"
        ],
        "summary": "Create Alert Rule",
        "description": "Create a new alert rule.",
        "operationId": "create_alert_rule_api_v1_alerts_rules_post",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/rules/{rule_id}": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get Alert Rule",
        "description": "Get a single alert rule by ID.",
        "operationId": "get_alert_rule_api_v1_alerts_rules__rule_id__get",
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Alert rule ID",
              "title": "Rule Id"
            },
            "description": "Alert rule ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Alerts"
        ],
        "summary": "Update Alert Rule",
        "description": "Update an alert rule.",
        "operationId": "update_alert_rule_api_v1_alerts_rules__rule_id__patch",
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Alert rule ID",
              "title": "Rule Id"
            },
            "description": "Alert rule ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AlertRuleUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Alerts"
        ],
        "summary": "Delete Alert Rule",
        "description": "Delete an alert rule and its history.",
        "operationId": "delete_alert_rule_api_v1_alerts_rules__rule_id__delete",
        "parameters": [
          {
            "name": "rule_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Alert rule ID",
              "title": "Rule Id"
            },
            "description": "Alert rule ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/history": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "List Alert History",
        "description": "List alert history for the current organization.",
        "operationId": "list_alert_history_api_v1_alerts_history_get",
        "parameters": [
          {
            "name": "rule_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by alert rule ID",
              "title": "Rule Id"
            },
            "description": "Filter by alert rule ID"
          },
          {
            "name": "alert_type",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/AlertType"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by alert type",
              "title": "Alert Type"
            },
            "description": "Filter by alert type"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertHistoryListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors": {
      "post": {
        "tags": [
          "Monitors"
        ],
        "summary": "Create Monitor",
        "description": "Create a new change detection monitor.",
        "operationId": "create_monitor_api_v1_monitors_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MonitorCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "List Monitors",
        "description": "List user's monitors.",
        "operationId": "list_monitors_api_v1_monitors_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "active_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false,
              "title": "Active Only"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "Get Monitor",
        "description": "Get monitor details.",
        "operationId": "get_monitor_api_v1_monitors__monitor_id__get",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Monitors"
        ],
        "summary": "Update Monitor",
        "description": "Update a monitor.",
        "operationId": "update_monitor_api_v1_monitors__monitor_id__patch",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MonitorUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Monitors"
        ],
        "summary": "Delete Monitor",
        "description": "Soft-delete a monitor.",
        "operationId": "delete_monitor_api_v1_monitors__monitor_id__delete",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/pause": {
      "post": {
        "tags": [
          "Monitors"
        ],
        "summary": "Pause Monitor",
        "description": "Pause a monitor.",
        "operationId": "pause_monitor_api_v1_monitors__monitor_id__pause_post",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/resume": {
      "post": {
        "tags": [
          "Monitors"
        ],
        "summary": "Resume Monitor",
        "description": "Resume a paused monitor.",
        "operationId": "resume_monitor_api_v1_monitors__monitor_id__resume_post",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/snapshots": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "List Snapshots",
        "description": "List snapshots for a monitor (most recent first).",
        "operationId": "list_snapshots_api_v1_monitors__monitor_id__snapshots_get",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/snapshots/{snapshot_id}": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "Get Snapshot",
        "description": "Get a specific snapshot with full content.",
        "operationId": "get_snapshot_api_v1_monitors__monitor_id__snapshots__snapshot_id__get",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "snapshot_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Snapshot Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SnapshotDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/diffs": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "List Changes",
        "description": "List detected changes for a monitor (most recent first).",
        "operationId": "list_changes_api_v1_monitors__monitor_id__diffs_get",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangeListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/{monitor_id}/diffs/{change_id}": {
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "Get Change",
        "description": "Get a specific change record.",
        "operationId": "get_change_api_v1_monitors__monitor_id__diffs__change_id__get",
        "parameters": [
          {
            "name": "monitor_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Monitor Id"
            }
          },
          {
            "name": "change_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Change Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChangeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/monitors/groups": {
      "post": {
        "tags": [
          "Monitors"
        ],
        "summary": "Create a monitor group",
        "description": "Create a group of monitors from a single config applied to multiple URLs. Each URL gets its own monitor schedule; all share the same group_id, extraction schema, webhook, cron, and diff configuration. Max 20 URLs per group.",
        "operationId": "create_monitor_group_api_v1_monitors_groups_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MonitorGroupCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Group created — N monitors created and linked by group_id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorGroupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid URL or SSRF violation"
          },
          "403": {
            "description": "Schedule limit reached for your balance tier"
          },
          "422": {
            "description": "Invalid request parameters"
          }
        }
      },
      "get": {
        "tags": [
          "Monitors"
        ],
        "summary": "List monitor groups",
        "description": "List all monitor groups owned by the current user. Returns aggregate status: group_id, total monitors, active monitors, and URLs.",
        "operationId": "list_monitor_groups_api_v1_monitors_groups_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MonitorGroupListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/stripe": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Stripe Webhook",
        "description": "Stripe webhook handler with full event processing (PAYG model).\n\nHandles:\n- checkout.session.created: Schedule abandonment recovery emails (+1h, +24h)\n- checkout.session.completed: Grant balance credits for deposits + auto-recharge setup; cancel recovery emails\n- checkout.session.expired: Release promo code reservations\n- payment_intent.succeeded: Auto-recharge balance grants (type=auto_recharge)\n- payment_intent.payment_failed: Auto-recharge failure tracking (type=auto_recharge)\n- payment_intent.requires_action: Auto-recharge SCA/3DS handling (type=auto_recharge)\n- customer.subscription.*: Sync subscription status (no plan-based logic)\n- customer.updated: Sync customer default payment method\n- invoice.created: Store invoice record for audit trail\n- invoice.upcoming: Log upcoming invoices\n- invoice.payment_succeeded: Store invoice payment record\n- invoice.payment_failed: Notify user of payment failure\n- payment_method.attached/detached/updated: Sync payment methods + auto-recharge PM lifecycle\n- setup_intent.succeeded: Set default payment method\n- radar.early_fraud_warning.created: Handle fraud alerts\n- charge.refunded: Debit user balance when Stripe refund fires (chargeback or admin refund)\n- charge.dispute.created: Flag user account on chargeback dispute, notify admins\n\nSecurity:\n- Verifies webhook signature using Stripe webhook secret\n- Uses idempotency keys to prevent duplicate processing\n- Logs all events to webhook_events table for audit trail",
        "operationId": "stripe_webhook_api_v1_webhooks_stripe_post",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/webhooks/{token}": {
      "post": {
        "tags": [
          "Workflow Webhooks"
        ],
        "summary": "Public Webhook Trigger",
        "description": "Trigger a workflow via its shareable trigger URL.\n\nNo authentication required — the token IS the credential.  External\nsystems POST to this endpoint; the request body is injected as\n``trigger_data`` into any ``webhook_trigger`` nodes.\n\nReturns 404 for missing or revoked tokens (no information leakage).\nReturns 400 for inactive (draft/archived) workflows.\nReturns 429 when the per-token rate limit (10 req/min) is exceeded.",
        "operationId": "public_webhook_trigger_api_v1_webhooks__token__post",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Token"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunTriggerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user-webhooks": {
      "get": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "List Webhooks",
        "description": "List all webhooks for the current organization.",
        "operationId": "list_webhooks_api_v1_user_webhooks_get",
        "parameters": [
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include disabled webhooks",
              "default": false,
              "title": "Include Inactive"
            },
            "description": "Include disabled webhooks"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Create Webhook",
        "description": "Create a new webhook endpoint for the current organization.",
        "operationId": "create_webhook_api_v1_user_webhooks_post",
        "parameters": [
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user-webhooks/{webhook_id}": {
      "get": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Get Webhook",
        "description": "Get webhook details with recent deliveries.",
        "operationId": "get_webhook_api_v1_user_webhooks__webhook_id__get",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Update Webhook",
        "description": "Update a webhook endpoint.",
        "operationId": "update_webhook_api_v1_user_webhooks__webhook_id__put",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Delete Webhook",
        "description": "Delete a webhook endpoint.",
        "operationId": "delete_webhook_api_v1_user_webhooks__webhook_id__delete",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user-webhooks/{webhook_id}/test": {
      "post": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Test Webhook",
        "description": "Send a test event to the webhook endpoint.",
        "operationId": "test_webhook_api_v1_user_webhooks__webhook_id__test_post",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user-webhooks/{webhook_id}/rotate-secret": {
      "post": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "Rotate Webhook Secret",
        "description": "Rotate the signing secret for a webhook.",
        "operationId": "rotate_webhook_secret_api_v1_user_webhooks__webhook_id__rotate_secret_post",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user-webhooks/{webhook_id}/deliveries": {
      "get": {
        "tags": [
          "User Webhooks"
        ],
        "summary": "List Webhook Deliveries",
        "description": "List delivery history for a webhook.",
        "operationId": "list_webhook_deliveries_api_v1_user_webhooks__webhook_id__deliveries_get",
        "parameters": [
          {
            "name": "webhook_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Webhook ID",
              "title": "Webhook Id"
            },
            "description": "Webhook ID"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/WebhookDeliveryStatus"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "X-Organization-Id",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Organization-Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/feedback/scrape": {
      "post": {
        "tags": [
          "Feedback",
          "feedback"
        ],
        "summary": "Submit Scrape Feedback",
        "description": "Submit feedback about a scrape result.\n\nThis endpoint allows users to report issues with their scrape results.\nThe feedback is:\n1. Validated against the job record\n2. Enriched with job metadata\n3. Stored in Redis for Cortex consumption\n4. Queued for immediate analysis\n\nSECURITY: Rate limited to 10 requests per minute per user to prevent\nRedis queue flooding and abuse.\n\nArgs:\n    request: The feedback request with job_id and issue details\n    user: The authenticated user (from API key or session)\n\nReturns:\n    ScrapeFeedbackResponse with feedback_id and status",
        "operationId": "submit_scrape_feedback_api_v1_feedback_scrape_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScrapeFeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeFeedbackResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/categories": {
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "List active ticket categories",
        "description": "List all active support ticket categories (public — no auth required).",
        "operationId": "list_categories_api_v1_support_categories_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CategoryListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/response-time-hint": {
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Get per-priority SLA response time hints",
        "description": "Return per-priority first-response SLA targets (hours) and the 30-day\naverage response time from the admin stats Redis cache (read-only).\n\nNo database queries — reads from in-memory constants + optional Redis cache.",
        "operationId": "get_response_time_hint_api_v1_support_response_time_hint_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseTimeHintResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/public": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Submit a contact form (unauthenticated)",
        "description": "Create a support ticket from the public /contact form without authentication.\n\nAnti-abuse measures:\n- IP-based sliding-window rate limit: 3 requests per hour per IP.\n- Honeypot field: if ``payload.website`` is non-empty the request is silently\n  accepted (returns 201) but no ticket is created. This prevents bots from\n  learning that they were detected.\n- If the submitter email matches an existing user, the ticket is linked to\n  that user account.\n\nSource is always ``contact_form``.",
        "operationId": "create_public_ticket_api_v1_support_tickets_public_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicTicketCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicTicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Create a support ticket",
        "description": "Create a new support ticket.\n\nThe ``body`` field becomes the first reply on the ticket. Rate-limited to\n5 ticket creations per hour per user.",
        "operationId": "create_ticket_api_v1_support_tickets_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "List own tickets",
        "description": "List the current user's support tickets with optional filters.\n\nSupports filtering by status, priority, category slug, full-text\nsearch on subject, and unread status. Paginated with offset-based pagination.",
        "operationId": "list_tickets_api_v1_support_tickets_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/TicketStatus"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "priority",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/TicketPriority"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Priority"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Category slug",
              "title": "Category"
            },
            "description": "Category slug"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 500
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search"
            }
          },
          {
            "name": "has_unread",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter to tickets with unread admin replies",
              "title": "Has Unread"
            },
            "description": "Filter to tickets with unread admin replies"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Page Size"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/read": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Mark ticket as read",
        "description": "Upsert a read receipt for the current user on the given ticket.\n\nSets ``last_read_at`` to ``NOW()``. Returns 204 on success.\nThe ticket must belong to the current user (non-admin).",
        "operationId": "mark_ticket_read_api_v1_support_tickets__ticket_id__read_post",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}": {
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Get ticket detail",
        "description": "Get the full detail of a single ticket belonging to the current user.",
        "operationId": "get_ticket_api_v1_support_tickets__ticket_id__get",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Update own ticket",
        "description": "Update mutable fields on an existing ticket owned by the current user.\n\nOnly ``status``, ``priority``, and ``category_id`` may be changed by the\nticket owner.  All fields are optional — send only the keys you want to\nchange.\n\nStatus restrictions for users:\n- Permitted: ``open``, ``closed``, ``resolved``\n- Forbidden: ``awaiting_reply``, ``in_progress``, ``merged`` — those are\n  set by agents and admins only.  Attempting to set a forbidden status\n  returns HTTP 422.\n\nAdmin-only fields (``assigned_to``, ``tags``) are rejected with HTTP 403\nwhen present in the request.",
        "operationId": "update_ticket_api_v1_support_tickets__ticket_id__patch",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/replies": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Add reply to ticket",
        "description": "Add a reply to an existing ticket.\n\nUsers cannot post internal notes (``is_internal_note`` is ignored and\nforced to ``False``). Rate-limited to 30 replies per hour per user.",
        "operationId": "create_reply_api_v1_support_tickets__ticket_id__replies_post",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplyCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "List ticket replies",
        "description": "List all non-deleted, non-internal replies for a ticket.\n\nInternal notes (admin-only) are excluded from the response.",
        "operationId": "list_replies_api_v1_support_tickets__ticket_id__replies_get",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Page Size"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReplyListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/close": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Close own ticket",
        "description": "Close an open ticket.\n\nIdempotent — closing an already-closed ticket returns 200 without error.",
        "operationId": "close_ticket_api_v1_support_tickets__ticket_id__close_post",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/reopen": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Reopen own ticket",
        "description": "Reopen a closed ticket.\n\nIdempotent — reopening an already-open ticket returns 200 without error.\nSets status back to ``open``.",
        "operationId": "reopen_ticket_api_v1_support_tickets__ticket_id__reopen_post",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/satisfaction": {
      "post": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Rate resolved ticket",
        "description": "Submit a CSAT satisfaction rating for a resolved or closed ticket.\n\nOnly tickets in ``resolved`` or ``closed`` status can be rated.\nRating can be updated by submitting again (last-write wins).",
        "operationId": "submit_satisfaction_api_v1_support_tickets__ticket_id__satisfaction_post",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SatisfactionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/preferences": {
      "get": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Get notification preferences",
        "description": "Return the authenticated user's support notification preferences.\n\nA preferences row is created with all-ON defaults on the first request if\nit doesn't exist yet (lazy initialisation — no setup required).",
        "operationId": "get_support_preferences_api_v1_support_preferences_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportPreferencesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Update notification preferences",
        "description": "Update the authenticated user's support notification preferences.\n\nSend only the keys you want to change — omitted keys are left as-is.\nChanges take effect immediately on the next notification event.",
        "operationId": "update_support_preferences_api_v1_support_preferences_patch",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SupportPreferencesPatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SupportPreferencesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/mute": {
      "patch": {
        "tags": [
          "Support",
          "Support"
        ],
        "summary": "Mute or unmute ticket notifications",
        "description": "Mute or unmute email notifications for a specific ticket.\n\nWhen a ticket is muted, email notifications for that ticket are suppressed\nregardless of the user's global notification preferences. In-app\nnotifications are unaffected (they are always shown).\n\nOnly the ticket owner can mute/unmute their own ticket.",
        "operationId": "mute_ticket_api_v1_support_tickets__ticket_id__mute_patch",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TicketMuteRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TicketMuteResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/tickets/{ticket_id}/gdpr": {
      "delete": {
        "tags": [
          "Support"
        ],
        "summary": "Delete a ticket and all associated data (GDPR erasure request)",
        "description": "Permanently soft-delete a ticket as part of a GDPR erasure request.\n\nThe ticket is immediately soft-deleted (deleted_at is set to now).\nThe weekly retention job will hard-delete or anonymize the row once the\nconfigured retention period passes.\n\nOnly the ticket owner can delete their own ticket. Admin deletion /\nanonymization is available via POST /api/v1/admin/support/gdpr/anonymize/{id}.\n\nThis endpoint is idempotent: a second call on an already-deleted ticket\nreturns HTTP 200 with deleted=False rather than 404.",
        "operationId": "gdpr_delete_ticket_api_v1_support_tickets__ticket_id__gdpr_delete",
        "parameters": [
          {
            "name": "ticket_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Ticket Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GdprTicketDeleteResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/blog/comments": {
      "post": {
        "tags": [
          "Blog"
        ],
        "summary": "Submit Comment",
        "description": "Submit a comment (public, optional auth).",
        "operationId": "submit_comment_api_v1_blog_comments_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/blog/feed.xml": {
      "get": {
        "tags": [
          "Blog"
        ],
        "summary": "Rss Feed",
        "description": "Public RSS 2.0 feed of published posts.",
        "operationId": "rss_feed_api_v1_blog_feed_xml_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    },
    "/api/v1/blog/posts/{slug}/reactions": {
      "get": {
        "tags": [
          "Blog"
        ],
        "summary": "Get Reactions",
        "description": "Get reaction counts for a blog post (public).",
        "operationId": "get_reactions_api_v1_blog_posts__slug__reactions_get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/blog/posts/{slug}/react": {
      "post": {
        "tags": [
          "Blog"
        ],
        "summary": "React To Post",
        "description": "Add a reaction to a blog post (public, rate-limited per IP).",
        "operationId": "react_to_post_api_v1_blog_posts__slug__react_post",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/announcement/active": {
      "get": {
        "tags": [
          "Announcement"
        ],
        "summary": "Get Active Announcement",
        "description": "Return the current announcement config for the homepage banner.\n\nCached in Redis for 60 seconds. Falls back to a DB query on cache miss.",
        "operationId": "get_active_announcement_api_v1_announcement_active_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAnnouncementResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/diagnostics/public/difficulty": {
      "get": {
        "tags": [
          "Diagnostics (Public)"
        ],
        "summary": "Get Public Antibot Difficulty",
        "description": "Return normalized vendor-level anti-bot difficulty scores.\n\nCached in Redis for 15 minutes. Falls back to a DB query on cache miss.\nOnly vendor-level aggregates are returned — no per-domain rows, no COGS\nfields, no raw bypass-success percentage.",
        "operationId": "get_public_antibot_difficulty_api_v1_diagnostics_public_difficulty_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "default": 7,
              "title": "Days"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAntibotDifficultyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/maintenance/active": {
      "get": {
        "tags": [
          "Maintenance"
        ],
        "summary": "Get Active Maintenance",
        "description": "Return the currently-active maintenance window (or null) plus upcoming\nscheduled windows.\n\nDegrades gracefully on failure: a Redis or DB error returns \"no\nmaintenance\" rather than raising, so a maintenance-subsystem outage can\nnever itself take down the marketing site.",
        "operationId": "get_active_maintenance_api_v1_maintenance_active_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicMaintenanceResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analytics/events": {
      "post": {
        "tags": [
          "Analytics"
        ],
        "summary": "Ingest Beacon Events",
        "description": "Ingest a batch of beacon events from the frontend.\n\nEvents are pushed to Redis for async processing by the EventService.\nThis endpoint is intentionally unauthenticated — it accepts both\nanonymous and authenticated events. Rate limited per IP.\n\nReturns 202 Accepted immediately (fire-and-forget semantics).",
        "operationId": "ingest_beacon_events_api_v1_analytics_events_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BeaconBatch"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analytics/funnels": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "List Funnels",
        "description": "List available funnel definitions.\n\nRequires admin privileges.",
        "operationId": "list_funnels_api_v1_analytics_funnels_get",
        "parameters": [
          {
            "name": "args",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Args"
            }
          },
          {
            "name": "kwargs",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Kwargs"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response List Funnels Api V1 Analytics Funnels Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analytics/funnels/{funnel_name}": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get Funnel Stats",
        "description": "Get step counts and conversion rates for a specific funnel.\n\nRequires admin privileges.\n\nParameters\n----------\nfunnel_name : str\n    One of: acquisition, activation, monetization, ecosystem\ndays : int\n    Lookback window in days (default 30, max 365).",
        "operationId": "get_funnel_stats_api_v1_analytics_funnels__funnel_name__get",
        "parameters": [
          {
            "name": "funnel_name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Funnel Name"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 365,
              "minimum": 1,
              "default": 30,
              "title": "Days"
            }
          },
          {
            "name": "args",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Args"
            }
          },
          {
            "name": "kwargs",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Kwargs"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get Funnel Stats Api V1 Analytics Funnels  Funnel Name  Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/analytics/funnels-all": {
      "get": {
        "tags": [
          "Analytics"
        ],
        "summary": "Get All Funnel Stats",
        "description": "Get stats for all defined funnels in a single request.\n\nRequires admin privileges.",
        "operationId": "get_all_funnel_stats_api_v1_analytics_funnels_all_get",
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 365,
              "minimum": 1,
              "default": 30,
              "title": "Days"
            }
          },
          {
            "name": "args",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Args"
            }
          },
          {
            "name": "kwargs",
            "in": "query",
            "required": true,
            "schema": {
              "title": "Kwargs"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "title": "Response Get All Funnel Stats Api V1 Analytics Funnels All Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/unsubscribe": {
      "post": {
        "tags": [
          "Email Unsubscribe"
        ],
        "summary": "Unsubscribe from lifecycle emails",
        "description": "Public endpoint — no auth required. Validates HMAC token from email link.",
        "operationId": "unsubscribe_api_v1_unsubscribe_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnsubscribeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnsubscribeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/providers": {
      "get": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "List Providers",
        "description": "Get list of supported proxy providers with their info.",
        "operationId": "list_providers_api_v1_integrations_proxies_providers_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "items": {
                    "$ref": "#/components/schemas/ProxyProviderInfo"
                  },
                  "type": "array",
                  "title": "Response List Providers Api V1 Integrations Proxies Providers Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies": {
      "get": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "List Integrations",
        "description": "List all proxy integrations for the authenticated user.",
        "operationId": "list_integrations_api_v1_integrations_proxies_get",
        "parameters": [
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include disabled integrations",
              "default": false,
              "title": "Include Inactive"
            },
            "description": "Include disabled integrations"
          },
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/ProxyProvider"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by provider",
              "title": "Provider"
            },
            "description": "Filter by provider"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Create Integration",
        "description": "Create a new proxy integration by connecting to a provider.",
        "operationId": "create_integration_api_v1_integrations_proxies_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProxyIntegrationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/reorder": {
      "put": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Batch Reorder Integrations",
        "description": "Batch reorder proxy integrations by priority.\n\nThis endpoint allows reordering multiple integrations at once by setting their priorities.\nLower priority numbers mean higher priority (0 = highest).\nThe top-most ENABLED integration automatically becomes the default.",
        "operationId": "batch_reorder_integrations_api_v1_integrations_proxies_reorder_put",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProxyIntegrationBatchReorder"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}": {
      "get": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Get Integration",
        "description": "Get detailed proxy integration info with endpoints.",
        "operationId": "get_integration_api_v1_integrations_proxies__integration_id__get",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Update Integration",
        "description": "Update a proxy integration.",
        "operationId": "update_integration_api_v1_integrations_proxies__integration_id__put",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProxyIntegrationUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Delete Integration",
        "description": "Delete a proxy integration.",
        "operationId": "delete_integration_api_v1_integrations_proxies__integration_id__delete",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}/test": {
      "post": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Test Integration",
        "description": "Test proxy integration connectivity.",
        "operationId": "test_integration_api_v1_integrations_proxies__integration_id__test_post",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProxyIntegrationTestRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationTestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}/refresh": {
      "post": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Refresh Endpoints",
        "description": "Refresh cached proxy endpoints from the provider.",
        "operationId": "refresh_endpoints_api_v1_integrations_proxies__integration_id__refresh_post",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}/validate": {
      "post": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Validate Integration",
        "description": "Re-validate credentials with the provider.",
        "operationId": "validate_integration_api_v1_integrations_proxies__integration_id__validate_post",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationValidateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}/default": {
      "put": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Set Default Integration",
        "description": "Set an integration as the default for scraping requests.",
        "operationId": "set_default_integration_api_v1_integrations_proxies__integration_id__default_put",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProxyIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/proxies/{integration_id}/usage": {
      "get": {
        "tags": [
          "Proxy Integrations"
        ],
        "summary": "Get Provider Usage",
        "description": "Get usage statistics from the proxy provider's API.",
        "operationId": "get_provider_usage_api_v1_integrations_proxies__integration_id__usage_get",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Integration ID",
              "title": "Integration Id"
            },
            "description": "Integration ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderUsageStats"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports": {
      "post": {
        "tags": [
          "Extension Reports"
        ],
        "summary": "Create Report",
        "description": "Create a new shareable scrapability report.\n\nPublic endpoint — no authentication required.\nRate limited to 10 reports/hour per IP.",
        "operationId": "create_report_api_v1_reports_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReportCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/reports/{report_id}": {
      "get": {
        "tags": [
          "Extension Reports"
        ],
        "summary": "Get Report",
        "description": "Retrieve a scrapability report by ID.\n\nPublic endpoint — no authentication required.",
        "operationId": "get_report_api_v1_reports__report_id__get",
        "parameters": [
          {
            "name": "report_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Report Id"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/public-key": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get encryption public key",
        "description": "Get the server's RSA public key for zero-knowledge cookie encryption. Clients wrap ephemeral AES-256-GCM session keys with this key before sending encrypted cookies. The key is versioned for rotation.",
        "operationId": "get_session_public_key_api_v1_sessions_public_key_get",
        "responses": {
          "200": {
            "description": "RSA public key in PEM format with version identifier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKeyResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/profiles": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "List session profiles",
        "description": "List all available pre-built session profile templates. Profiles provide cookie requirements, capture instructions, and validation info for popular sites. No authentication required.",
        "operationId": "list_session_profiles_api_v1_sessions_profiles_get",
        "responses": {
          "200": {
            "description": "List of session profile summaries grouped by category",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionProfileListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/profiles/{slug}": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get a session profile",
        "description": "Get full profile details including capture instructions, required/optional cookies, recommended tier, and validation URL. Accepts either a profile slug (e.g. 'amazon') or a domain (e.g. 'amazon.com'). No authentication required.",
        "operationId": "get_session_profile_api_v1_sessions_profiles__slug__get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Profile slug (e.g. 'amazon') or domain (e.g. 'amazon.com')",
              "title": "Slug"
            },
            "description": "Profile slug (e.g. 'amazon') or domain (e.g. 'amazon.com')"
          }
        ],
        "responses": {
          "200": {
            "description": "Profile found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionProfileResponse"
                }
              }
            }
          },
          "404": {
            "description": "No profile for this slug or domain"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Create a session",
        "description": "Create a new session integration with encrypted cookies. Stores browser cookies for a specific domain to enable authenticated scraping. Cookies are encrypted at rest with AES-256-GCM and never returned in plaintext. Rate limited to 10 creations per hour per user.",
        "operationId": "create_session_api_v1_sessions_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Session created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid domain, duplicate session, or cookie validation failed"
          },
          "429": {
            "description": "Rate limit exceeded (10 per hour)"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "List sessions",
        "description": "List session integrations for the authenticated user. Pass `include_shared=true` to include organization-shared sessions. Cookie values are never returned — only cookie names.",
        "operationId": "list_sessions_api_v1_sessions_get",
        "parameters": [
          {
            "name": "include_shared",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include organization-shared sessions from teams you belong to",
              "default": false,
              "title": "Include Shared"
            },
            "description": "Include organization-shared sessions from teams you belong to"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of sessions with metadata (no cookie values)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/org": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "List organization sessions",
        "description": "List sessions split into personal and team views for a specific organization. Returns personal sessions (owned by you) and team sessions (shared by other members). Requires org membership.",
        "operationId": "list_org_sessions_api_v1_sessions_org_get",
        "parameters": [
          {
            "name": "organization_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Organization ID to list sessions for",
              "title": "Organization Id"
            },
            "description": "Organization ID to list sessions for"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Personal and team session lists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrgSessionListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get session details",
        "description": "Get a single session integration. Returns cookie names only — values are never exposed. Accessible if you own the session or if it is shared with your organization.",
        "operationId": "get_session_api_v1_sessions__session_id__get",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found or not accessible"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Update a session",
        "description": "Update name, cookies, headers, expiry, or notes. If cookies are provided, old cookies are replaced entirely (not merged). New cookies are encrypted with domain binding. Only the owner or org admin can update.",
        "operationId": "update_session_api_v1_sessions__session_id__patch",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found or not accessible"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Delete a session",
        "description": "Soft-delete a session integration. The session is marked as deleted but retained for audit purposes. Encrypted cookies remain but are no longer usable. Only the owner or org admin can delete.",
        "operationId": "delete_session_api_v1_sessions__session_id__delete",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Session deleted"
          },
          "404": {
            "description": "Session not found or not accessible"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/share": {
      "patch": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Share session with organization",
        "description": "Make a session visible to all members of its organization. Only the session owner or an org admin can share.",
        "operationId": "share_session_api_v1_sessions__session_id__share_patch",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/SessionShareRequest"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Payload"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session shared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "409": {
            "description": "Session already shared or no organization assigned"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/unshare": {
      "patch": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Unshare session from organization",
        "description": "Revoke sharing of a session. The session remains assigned to the organization but is no longer visible to other members.",
        "operationId": "unshare_session_api_v1_sessions__session_id__unshare_patch",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session unshared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "409": {
            "description": "Session is not currently shared"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/audit": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get session audit log",
        "description": "Get the audit trail for a session: creation, updates, sharing, validation, and deletion events. Only the owner or org admin can view.",
        "operationId": "get_session_audit_log_api_v1_sessions__session_id__audit_get",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "description": "Maximum entries to return",
              "default": 50,
              "title": "Limit"
            },
            "description": "Maximum entries to return"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Offset for pagination",
              "default": 0,
              "title": "Offset"
            },
            "description": "Offset for pagination"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit log returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionAuditResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/validate": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Validate a session",
        "description": "Check whether stored session cookies are still valid using domain-specific heuristics. Returns a confidence score (0-100), detected username, and cookie expiry warnings. After 3 consecutive failures the session is auto-marked as expired. Rate limited to 30 validations per hour.",
        "operationId": "validate_session_api_v1_sessions__session_id__validate_post",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Validation completed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionValidationResult"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "429": {
            "description": "Rate limit exceeded"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/refresh": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Refresh session cookies",
        "description": "Re-upload cookies for a session (rotation shortcut). Replaces all stored cookies and resets validation status. Use after re-authenticating in your browser.",
        "operationId": "refresh_session_cookies_api_v1_sessions__session_id__refresh_post",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionRefreshRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cookies refreshed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/health-check": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Trigger Session Health Check",
        "description": "Run a periodic health check on all active sessions.\n\n**Admin only.** Scans for sessions approaching expiry, marks expired\nsessions, and creates notifications. This endpoint is idempotent and safe\nto call frequently -- sessions are skipped if they were checked within the\nlast 6 hours.\n\nTypically called by a cron job every 6 hours, but can be triggered manually\nby a platform admin.",
        "operationId": "trigger_session_health_check_api_v1_sessions_health_check_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionHealthCheckResult"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/auto-refresh": {
      "patch": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Update auto-refresh settings",
        "description": "Update auto-refresh and notification preferences for a session. Controls whether the session participates in periodic health checks and whether you receive expiry notifications.",
        "operationId": "update_auto_refresh_settings_api_v1_sessions__session_id__auto_refresh_patch",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionAutoRefreshSettings"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated session with new auto-refresh settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/kill-all": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Emergency: deactivate all sessions",
        "description": "Emergency kill switch — immediately deactivate ALL sessions for your account. Sessions are NOT deleted and can be reactivated individually. Use when account compromise is suspected.",
        "operationId": "kill_all_sessions_api_v1_sessions_kill_all_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Count of deactivated sessions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KillAllResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/deactivate": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Deactivate a session",
        "description": "Deactivate a single session (non-destructive). Immediately stops the session from being used in scrapes. Can be reactivated later via POST /{session_id}/reactivate.",
        "operationId": "deactivate_single_session_api_v1_sessions__session_id__deactivate_post",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session deactivated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeactivateSessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/reactivate": {
      "post": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Reactivate a session",
        "description": "Restore a previously deactivated session to active status and remove the invalidation flag from Redis.",
        "operationId": "reactivate_single_session_api_v1_sessions__session_id__reactivate_post",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Session reactivated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactivateSessionResponse"
                }
              }
            }
          },
          "404": {
            "description": "Session not found"
          },
          "409": {
            "description": "Session is not deactivated"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/access-log": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get session access log",
        "description": "Get timestamped entries showing when and from where the session was accessed (last 7 days). Raw IPs are only shown within 1 hour of access; after that, only the hashed representation is shown.",
        "operationId": "get_session_access_log_api_v1_sessions__session_id__access_log_get",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "description": "Max entries to return",
              "default": 50,
              "title": "Limit"
            },
            "description": "Max entries to return"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Access log entries with timestamps and source info",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccessLogResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/{session_id}/security": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get session security summary",
        "description": "Security overview for the session detail panel: known source counts, recent access summary, and alert preferences.",
        "operationId": "get_session_security_summary_api_v1_sessions__session_id__security_get",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Security summary with source counts and alert settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecuritySummary"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/alerts/preferences": {
      "get": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Get session alert preferences",
        "description": "Get the current session alert notification preferences for your account.",
        "operationId": "get_alert_preferences_endpoint_api_v1_sessions_alerts_preferences_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert preference settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionAlertPreferencesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Session Integrations (BYOS)"
        ],
        "summary": "Update session alert preferences",
        "description": "Update session alert notification preferences. Only provided fields are updated; omitted fields keep their current value. Changes take effect immediately.",
        "operationId": "update_alert_preferences_endpoint_api_v1_sessions_alerts_preferences_put",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SessionAlertPreferences"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated alert preference settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionAlertPreferencesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/privacy/export": {
      "get": {
        "tags": [
          "Session Privacy (GDPR)"
        ],
        "summary": "Export Session Data",
        "description": "GDPR right-to-access: export all session data for the current user.\n\nReturns session metadata (names, domains, cookie names, usage stats).\nCookie values are NEVER included in the export — only cookie names.\nIncludes data processing transparency information.",
        "operationId": "export_session_data_api_v1_sessions_privacy_export_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SessionDataExportResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/privacy/delete-all": {
      "delete": {
        "tags": [
          "Session Privacy (GDPR)"
        ],
        "summary": "Delete All Session Data",
        "description": "GDPR right-to-deletion: permanently purge ALL session data.\n\nThis is a hard delete — removes sessions from the database, clears\nRedis caches, and redacts audit log entries. This action is irreversible.\n\nUnlike the standard DELETE endpoint (soft-delete), this permanently\nremoves all traces of session cookie data.",
        "operationId": "delete_all_session_data_api_v1_sessions_privacy_delete_all_delete",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GDPRDeletionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/privacy/consent": {
      "post": {
        "tags": [
          "Session Privacy (GDPR)"
        ],
        "summary": "Record Consent",
        "description": "Record GDPR consent for session data processing.\n\nConsent is required before creating any session integrations.\nThis endpoint records the consent timestamp and can be called\nonce per user — subsequent calls update the timestamp.",
        "operationId": "record_consent_api_v1_sessions_privacy_consent_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GDPRConsentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GDPRConsentResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/privacy/retention": {
      "get": {
        "tags": [
          "Session Privacy (GDPR)"
        ],
        "summary": "Get Retention Policy",
        "description": "Get the current data retention policy for session data.\n\nReturns the configured retention periods and data residency information.",
        "operationId": "get_retention_policy_api_v1_sessions_privacy_retention_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetentionPolicyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/sessions/privacy/{session_id}/hard-delete": {
      "delete": {
        "tags": [
          "Session Privacy (GDPR)"
        ],
        "summary": "Hard Delete Single Session",
        "description": "GDPR hard-delete a single session.\n\nPermanently purges the session from the database, Redis cache,\nand redacts all associated audit log entries. Irreversible.\n\nOnly the session owner can hard-delete a session.",
        "operationId": "hard_delete_single_session_api_v1_sessions_privacy__session_id__hard_delete_delete",
        "parameters": [
          {
            "name": "session_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Session integration ID",
              "title": "Session Id"
            },
            "description": "Session integration ID"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GDPRDeletionResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/providers": {
      "get": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "List Providers",
        "description": "Get list of supported cloud storage providers with their info.",
        "operationId": "list_providers_api_v1_integrations_storage_providers_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/StorageProviderInfo"
                  },
                  "title": "Response List Providers Api V1 Integrations Storage Providers Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage": {
      "get": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "List Integrations",
        "description": "List all storage integrations for the authenticated user.",
        "operationId": "list_integrations_api_v1_integrations_storage_get",
        "parameters": [
          {
            "name": "include_inactive",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include disabled integrations",
              "default": false,
              "title": "Include Inactive"
            },
            "description": "Include disabled integrations"
          },
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "$ref": "#/components/schemas/StorageProvider"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by provider",
              "title": "Provider"
            },
            "description": "Filter by provider"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Create Integration",
        "description": "Create a new storage integration by connecting to a cloud provider.",
        "operationId": "create_integration_api_v1_integrations_storage_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StorageIntegrationCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/{integration_id}": {
      "get": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Get Integration",
        "description": "Get details of a specific storage integration.",
        "operationId": "get_integration_api_v1_integrations_storage__integration_id__get",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Update Integration",
        "description": "Update a storage integration's settings (not credentials).",
        "operationId": "update_integration_api_v1_integrations_storage__integration_id__put",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StorageIntegrationUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Delete Integration",
        "description": "Delete a storage integration.",
        "operationId": "delete_integration_api_v1_integrations_storage__integration_id__delete",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/{integration_id}/credentials": {
      "put": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Update Credentials",
        "description": "Update credentials for a storage integration. Triggers re-validation.",
        "operationId": "update_credentials_api_v1_integrations_storage__integration_id__credentials_put",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StorageIntegrationCredentialsUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/{integration_id}/test": {
      "post": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Test Integration",
        "description": "Test a storage integration by uploading and deleting a small test file.",
        "operationId": "test_integration_api_v1_integrations_storage__integration_id__test_post",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationTestResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/{integration_id}/validate": {
      "post": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Validate Integration",
        "description": "Validate credentials and bucket access for a storage integration.",
        "operationId": "validate_integration_api_v1_integrations_storage__integration_id__validate_post",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationValidateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/storage/{integration_id}/default": {
      "put": {
        "tags": [
          "Storage Integrations"
        ],
        "summary": "Set Default Integration",
        "description": "Set a storage integration as the default export destination.",
        "operationId": "set_default_integration_api_v1_integrations_storage__integration_id__default_put",
        "parameters": [
          {
            "name": "integration_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Integration Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorageIntegrationResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/active": {
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "Get Active Notifications",
        "description": "Get active, undismissed notifications for the current user.",
        "operationId": "get_active_notifications_api_v1_notifications_active_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActiveNotificationListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/history": {
      "get": {
        "tags": [
          "Notifications"
        ],
        "summary": "Get Notification History",
        "description": "Get all notifications for the current user, including dismissed ones.",
        "operationId": "get_notification_history_api_v1_notifications_history_get",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotificationHistoryListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/notifications/dismiss": {
      "post": {
        "tags": [
          "Notifications"
        ],
        "summary": "Dismiss Notification",
        "description": "Dismiss a notification for the current user (idempotent).",
        "operationId": "dismiss_notification_api_v1_notifications_dismiss_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DismissRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/kb/search": {
      "get": {
        "tags": [
          "Knowledge Base",
          "Knowledge Base"
        ],
        "summary": "Search knowledge base articles",
        "description": "Full-text search over published KB articles. Returns up to ``limit`` results ranked by relevance (ts_rank). Intended for the ticket-deflection UX: call this while the user types the ticket subject.",
        "operationId": "search_kb_articles_api_v1_support_kb_search_get",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500,
              "description": "Search query",
              "title": "Q"
            },
            "description": "Search query"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 20,
              "minimum": 1,
              "description": "Max results to return",
              "default": 3,
              "title": "Limit"
            },
            "description": "Max results to return"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KBSearchResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/kb/{slug}": {
      "get": {
        "tags": [
          "Knowledge Base",
          "Knowledge Base"
        ],
        "summary": "Get a published KB article by slug",
        "description": "Fetch a single published KB article by its slug. Increments view_count.",
        "operationId": "get_kb_article_by_slug_api_v1_support_kb__slug__get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KBArticleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/kb/{slug}/helpful": {
      "post": {
        "tags": [
          "Knowledge Base",
          "Knowledge Base"
        ],
        "summary": "Record whether an article was helpful",
        "description": "Increment helpful_count when a user marks an article as helpful.\n\nNot-helpful votes are accepted but do not affect any counter (reserved for\nfuture analytics). Only published articles accept feedback.",
        "operationId": "record_kb_helpful_api_v1_support_kb__slug__helpful_post",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KBHelpfulRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/upload": {
      "post": {
        "tags": [
          "Support Attachments"
        ],
        "summary": "Upload a file attachment",
        "description": "Upload a file to be attached to a support ticket or reply.  Returns a lightweight response containing the storage key, which the client passes to the ticket-creation or reply endpoints (via AttachmentRef).  The upload is bound to the authenticated user until the TicketAttachment row is created when the ticket or reply is saved. Storage keys are one-time-use.  **Storage keys expire after 24 hours.** Submitting a storage_key older than 24 h in a create_ticket or create_reply request may fail because the background GC can remove files with no DB row after that window.  Upload the file immediately before creating the ticket or reply.  Max 10 MB per file.  Allowed types: PNG, JPEG, GIF, WEBP, PDF, plain text, CSV, JSON.",
        "operationId": "upload_attachment_api_v1_support_upload_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_upload_attachment_api_v1_support_upload_post"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadAttachmentResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/support/attachments/{attachment_id}": {
      "get": {
        "tags": [
          "Support Attachments"
        ],
        "summary": "Download a file attachment",
        "description": "Stream the file associated with *attachment_id*.  Only the ticket owner or an admin may download the file.",
        "operationId": "download_attachment_api_v1_support_attachments__attachment_id__get",
        "parameters": [
          {
            "name": "attachment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Attachment Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Attachment content",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "206": {
            "description": "Partial attachment content for a range request",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "307": {
            "description": "Temporary redirect to a signed object-storage download URL",
            "headers": {
              "Location": {
                "description": "Signed attachment download URL",
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates/publish": {
      "post": {
        "tags": [
          "Template Marketplace"
        ],
        "summary": "Publish Template",
        "description": "Submit a user-owned workflow as a marketplace template.\n\nThe workflow graph is deep-copied and sanitized (UserSecret UUIDs replaced\nwith {{SECRET_NAME}} placeholders) before being stored on the template.\nThe template is created with publish_status='pending_review'; an admin\nmust approve it before it appears in the public gallery.\n\nPaid templates (price_cents > 0) require an onboarded Stripe Connect account.",
        "operationId": "publish_template_api_v1_workflows_templates_publish_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishTemplateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates/{template_id}/fork": {
      "post": {
        "tags": [
          "Template Marketplace"
        ],
        "summary": "Fork Template",
        "description": "Fork an approved template into a new user-owned workflow.\n\nUnlike /use (which creates an anonymous copy), fork records lineage in\nworkflow_template_forks and atomically increments template.fork_count.\nThe resulting workflow is identical to what /use creates, but the fork\nlineage allows future attribution and analytics.",
        "operationId": "fork_template_api_v1_workflows_templates__template_id__fork_post",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ForkTemplateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates/{template_id}/reviews": {
      "get": {
        "tags": [
          "Template Marketplace"
        ],
        "summary": "List Reviews",
        "description": "List reviews for an approved template.\n\navg_rating and review_count are read from the denormalized columns on\nWorkflowTemplate (atomically updated at review write time) to avoid\naggregating the full review set on every request.",
        "operationId": "list_reviews_api_v1_workflows_templates__template_id__reviews_get",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateReviewListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Template Marketplace"
        ],
        "summary": "Create Review",
        "description": "Post a rating and optional review for an approved template.\n\nOne review per user per template (UNIQUE constraint enforced in DDL).\nAfter insert, atomically updates WorkflowTemplate.avg_rating and\nreview_count using DB-level aggregation to avoid read-modify-write races.",
        "operationId": "create_review_api_v1_workflows_templates__template_id__reviews_post",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TemplateReviewCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateReviewItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates": {
      "get": {
        "tags": [
          "Workflow Templates"
        ],
        "summary": "List Templates",
        "description": "List available workflow templates with optional filtering.\n\nOnly returns templates with publish_status='approved'. Curated platform\ntemplates (author_id IS NULL) are approved by default (see migration 0154).\nUser-submitted templates appear after admin review.",
        "operationId": "list_templates_api_v1_workflows_templates_get",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by category",
              "title": "Category"
            },
            "description": "Filter by category"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Search by name or description",
              "title": "Search"
            },
            "description": "Search by name or description"
          },
          {
            "name": "featured",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter featured only",
              "title": "Featured"
            },
            "description": "Filter featured only"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowTemplateListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates/{template_id}": {
      "get": {
        "tags": [
          "Workflow Templates"
        ],
        "summary": "Get Template",
        "description": "Get a template by ID with full graph details.\n\nOnly returns approved templates. Unapproved/pending/rejected templates\nreturn 404 to prevent information leakage via UUID enumeration.",
        "operationId": "get_template_api_v1_workflows_templates__template_id__get",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowTemplateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/templates/{template_id}/use": {
      "post": {
        "tags": [
          "Workflow Templates"
        ],
        "summary": "Use Template",
        "description": "Create a new workflow from a template.\n\nCopies the template's graph into a new user-owned workflow,\napplying any config overrides the user provides.\n\nOnly approved templates can be used. Unapproved templates return 404.",
        "operationId": "use_template_api_v1_workflows_templates__template_id__use_post",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UseTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UseTemplateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Create Workflow",
        "description": "Create a new workflow.",
        "operationId": "create_workflow_api_v1_workflows_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List Workflows",
        "description": "List the current user's workflows.",
        "operationId": "list_workflows_api_v1_workflows_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by status",
              "title": "Status"
            },
            "description": "Filter by status"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/reusable": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List Reusable Workflows",
        "description": "List the current user's reusable workflows (is_reusable=true).\n\nUsed by the sub_workflow node picker in the visual editor to let users\nselect which workflow to call as a sub-workflow component.  Only returns\nworkflows that have been explicitly marked as reusable.",
        "operationId": "list_reusable_workflows_api_v1_workflows_reusable_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "minimum": 1,
              "default": 200,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Get Workflow",
        "description": "Get a workflow by ID.",
        "operationId": "get_workflow_api_v1_workflows__workflow_id__get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Workflows"
        ],
        "summary": "Update Workflow",
        "description": "Update a workflow's graph, settings, or metadata.",
        "operationId": "update_workflow_api_v1_workflows__workflow_id__patch",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Workflows"
        ],
        "summary": "Delete Workflow",
        "description": "Archive a workflow (soft delete).",
        "operationId": "delete_workflow_api_v1_workflows__workflow_id__delete",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/run": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Trigger Workflow Run",
        "description": "Trigger a new workflow execution.\n\nAccepts an optional JSON body with ``input_data`` to inject into any\n``webhook_trigger`` nodes as ``_trigger_data``, matching the behaviour of\nthe ``/trigger`` webhook endpoint.  Callers that send no body continue to\nwork unchanged.",
        "operationId": "trigger_workflow_run_api_v1_workflows__workflow_id__run_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/WorkflowRunRequest"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunTriggerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/validate": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Validate Workflow",
        "description": "Validate a workflow's graph structure and node configs.",
        "operationId": "validate_workflow_api_v1_workflows__workflow_id__validate_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowValidateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/estimate": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Estimate Workflow Cost",
        "description": "Estimate the credit cost of running a workflow.",
        "operationId": "estimate_workflow_cost_api_v1_workflows__workflow_id__estimate_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowEstimateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/runs": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List Workflow Runs",
        "description": "List execution runs for a workflow.",
        "operationId": "list_workflow_runs_api_v1_workflows__workflow_id__runs_get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/runs/{run_id}": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Get Workflow Run",
        "description": "Get a specific workflow run with node states.\n\nMerges persisted Postgres state with live Redis state for running workflows.",
        "operationId": "get_workflow_run_api_v1_workflows_runs__run_id__get",
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Run Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Workflows"
        ],
        "summary": "Cancel Workflow Run",
        "description": "Cancel a running workflow execution.",
        "operationId": "cancel_workflow_run_api_v1_workflows_runs__run_id__delete",
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Run Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/runs/{run_id}/stream": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Stream Workflow Run",
        "description": "SSE stream for real-time workflow run progress.\n\nPolls Redis for node state changes and emits events.\nCloses when the run completes, fails, or is cancelled.",
        "operationId": "stream_workflow_run_api_v1_workflows_runs__run_id__stream_get",
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Run Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/runs/{run_id}/retry": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Retry Workflow Run",
        "description": "Retry a failed/completed run from a specific node.\n\nCreates a new run using the original graph snapshot, carrying over\ncompleted node outputs for nodes before ``from_node``.  If no\n``from_node`` is given, the first failed node is used.",
        "operationId": "retry_workflow_run_api_v1_workflows_runs__run_id__retry_post",
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Run Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkflowRetryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunTriggerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/runs/{run_id}/export": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Export Workflow Run",
        "description": "Export workflow run data as CSV.",
        "operationId": "export_workflow_run_api_v1_workflows_runs__run_id__export_get",
        "parameters": [
          {
            "name": "run_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Run Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/trigger": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Webhook Trigger Workflow",
        "description": "Trigger a workflow via webhook (external integration).\n\nSame as /run but records triggered_by='webhook' and injects the\nrequest body as trigger_data into any webhook_trigger nodes.",
        "operationId": "webhook_trigger_workflow_api_v1_workflows__workflow_id__trigger_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowRunTriggerResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/token": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Generate Trigger Token",
        "description": "Generate or rotate the shareable webhook trigger token for a workflow.\n\nThe returned ``trigger_url`` can be POSTed to by external systems (Zapier,\nn8n, Slack) without supplying an API key.  The token itself IS the\ncredential — treat it like a secret.\n\nCalling this endpoint when a token already exists rotates it: the old\nURL stops working immediately upon commit.",
        "operationId": "generate_trigger_token_api_v1_workflows__workflow_id__token_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TriggerTokenResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Workflows"
        ],
        "summary": "Revoke Trigger Token",
        "description": "Revoke the webhook trigger token for a workflow.\n\nAfter revocation the trigger_url returns 404. The workflow itself is\nunaffected; it can still be run via authenticated endpoints.",
        "operationId": "revoke_trigger_token_api_v1_workflows__workflow_id__token_delete",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/analytics": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Get Workflow Analytics",
        "description": "Return aggregated analytics for a workflow over the last N days.\n\nComputes: success rate, duration percentiles (p50/p95), total cost,\ndaily run time-series, per-node-type cost breakdown, and step drop-off\n(fraction of runs each node type completed successfully).",
        "operationId": "get_workflow_analytics_api_v1_workflows__workflow_id__analytics_get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 365,
              "minimum": 1,
              "default": 30,
              "title": "Days"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkflowAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/sequences": {
      "post": {
        "tags": [
          "Workflows"
        ],
        "summary": "Enroll Contact List",
        "description": "Start a sequence run: enroll a contact list into this workflow.\n\nEach contact in the list gets its own independent WorkflowRun.\nContacts with status='replied' are skipped when auto_stop_on_reply=True (default).\nRate limiting caps how many contacts are dispatched per hour.",
        "operationId": "enroll_contact_list_api_v1_workflows__workflow_id__sequences_post",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceEnrollRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceEnrollmentItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List Sequence Enrollments",
        "description": "List sequence enrollments for a workflow.",
        "operationId": "list_sequence_enrollments_api_v1_workflows__workflow_id__sequences_get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceEnrollmentListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/sequences/{enrollment_id}": {
      "patch": {
        "tags": [
          "Workflows"
        ],
        "summary": "Update Sequence Enrollment",
        "description": "Pause or resume an entire sequence enrollment.",
        "operationId": "update_sequence_enrollment_api_v1_workflows__workflow_id__sequences__enrollment_id__patch",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "enrollment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Enrollment Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SequenceEnrollmentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceEnrollmentItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/sequences/{enrollment_id}/contacts": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "List Enrollment Contacts",
        "description": "List per-contact execution status for a sequence enrollment.",
        "operationId": "list_enrollment_contacts_api_v1_workflows__workflow_id__sequences__enrollment_id__contacts_get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "enrollment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Enrollment Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by contact run status",
              "title": "Status"
            },
            "description": "Filter by contact run status"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentContactRunListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/sequences/{enrollment_id}/contacts/{contact_id}": {
      "patch": {
        "tags": [
          "Workflows"
        ],
        "summary": "Update Enrollment Contact",
        "description": "Pause or resume a single contact within a sequence enrollment.\n\n- 'paused': skip this contact — will not be enqueued in subsequent batches\n- 'active': re-enable a paused contact so it can be dispatched",
        "operationId": "update_enrollment_contact_api_v1_workflows__workflow_id__sequences__enrollment_id__contacts__contact_id__patch",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "enrollment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Enrollment Id"
            }
          },
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Contact Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentContactRunUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentContactRunItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workflows/{workflow_id}/sequences/{enrollment_id}/analytics": {
      "get": {
        "tags": [
          "Workflows"
        ],
        "summary": "Get Sequence Enrollment Analytics",
        "description": "Return aggregated analytics for a single sequence enrollment.\n\nComputes:\n- Funnel metrics: total → dispatched → completed/failed/skipped/pending\n- Reply metrics: reply count/rate and classification breakdown from contact_reply_events\n- Conversion metrics: converted/bounced/unsubscribed counts from contacts.status\n- Variant metrics: per-variant reply/conversion rates when workflow contains ab_split node\n- Step metrics: per-node-type success rates across all contact runs",
        "operationId": "get_sequence_enrollment_analytics_api_v1_workflows__workflow_id__sequences__enrollment_id__analytics_get",
        "parameters": [
          {
            "name": "workflow_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Workflow Id"
            }
          },
          {
            "name": "enrollment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Enrollment Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SequenceAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/connect/onboard": {
      "post": {
        "tags": [
          "Creator Payouts"
        ],
        "summary": "Start Onboarding",
        "description": "Start Stripe Connect Express onboarding for creator payouts.\n\nCreates a Stripe Express account (if one doesn't exist), then generates\nan Account Link URL for the creator to complete KYC and bank setup on Stripe.\n\nStripe handles all identity verification, tax compliance (1099-K), and\nbank account validation. AlterLab stores only the Connect account ID.\n\nThe returned `onboarding_url` expires in approximately 1 hour.\nDirect the creator to this URL to complete onboarding.\n\nRate limited: 3 requests per hour per authenticated user (user-layer) plus\n5 requests per hour per IP (via RateLimitMiddleware, IP-layer).",
        "operationId": "start_onboarding_api_v1_creator_connect_onboard_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/connect/status": {
      "get": {
        "tags": [
          "Creator Payouts"
        ],
        "summary": "Get Connect Status",
        "description": "Return the current creator's Connect account status and payout eligibility.\n\nSurfaces:\n- Whether a Connect account has been created\n- KYC / onboarding completion status\n- Payout eligibility (KYC + threshold + not sanctioned)\n- Pending balance\n- 1099-K eligibility flag (US creators, $600+/year)",
        "operationId": "get_connect_status_api_v1_creator_connect_status_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/earnings": {
      "get": {
        "tags": [
          "Creator Payouts"
        ],
        "summary": "Get Earnings Summary",
        "description": "Return creator earnings summary and recent payout history.\n\nReturns total earnings (current year), pending payout balance, paid out\namount, and the 20 most recent payout events.\n\nRequires a Connect account to be created first via POST /creator/connect/onboard.",
        "operationId": "get_earnings_summary_api_v1_creator_earnings_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EarningsSummaryResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/storefront": {
      "get": {
        "tags": [
          "Creator Storefront"
        ],
        "summary": "Get My Storefront",
        "description": "Return the authenticated creator's storefront configuration.\n\nReturns 404 if the creator has not yet configured a storefront.",
        "operationId": "get_my_storefront_api_v1_creator_storefront_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorefrontResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Creator Storefront"
        ],
        "summary": "Upsert My Storefront",
        "description": "Create or update the authenticated creator's storefront.\n\nSlug is normalised via python-slugify (lowercase, hyphenated, max 64 chars)\nbefore storage. DB UNIQUE constraint enforces global uniqueness; a slug\nalready taken by another creator returns 409.\n\nReturns the full storefront record (including id, timestamps).\n\nCache invalidation: the public storefront cache for both the old and new\nslug is evicted AFTER db.commit() to prevent the stale re-cache window\ndescribed in review finding #16775.",
        "operationId": "upsert_my_storefront_api_v1_creator_storefront_put",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StorefrontUpsertRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorefrontResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/storefronts/{slug}": {
      "get": {
        "tags": [
          "Storefronts"
        ],
        "summary": "Get Public Storefront",
        "description": "Return a creator's public storefront: branding info + their approved templates.\n\nNo authentication required — this endpoint is designed to be loaded by\nunauthenticated buyers browsing the marketplace.\n\nReturns 404 when:\n  - No storefront exists for this slug\n  - Storefront exists but is_published=False (creator hasn't published yet)\n\nCaching (#17287): responses are cached in Redis for 60 s (TTL_SHORT) to absorb\nburst traffic from viral social shares. Cache-Control: public, max-age=60 allows\nCloudflare to serve the response from its edge cache for a further 60 s.",
        "operationId": "get_public_storefront_api_v1_storefronts__slug__get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-based).",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number (1-based)."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Templates per page (max 100).",
              "default": 50,
              "title": "Limit"
            },
            "description": "Templates per page (max 100)."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicStorefrontResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/subscription-plans": {
      "post": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "Create Subscription Plan",
        "description": "Create a monthly subscription plan (creator-only).\n\nCreates a Stripe Product and recurring Price, then stores the plan in\ncreator_subscription_plans. The creator must have completed Stripe Connect\nonboarding (KYC verified) before creating plans.\n\nRate limited: 10 plan-creation requests per hour per authenticated user.\n\nReturns the created plan including its Stripe Price ID.",
        "operationId": "create_subscription_plan_api_v1_creator_subscription_plans_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePlanRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "List Subscription Plans",
        "description": "List subscription plans owned by this creator.\n\nReturns plans newest-first. Archived plans are excluded by default.\nRequires the caller to be an onboarded creator.",
        "operationId": "list_subscription_plans_api_v1_creator_subscription_plans_get",
        "parameters": [
          {
            "name": "include_archived",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include archived (inactive) plans",
              "default": false,
              "title": "Include Archived"
            },
            "description": "Include archived (inactive) plans"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PlanResponse"
                  },
                  "title": "Response List Subscription Plans Api V1 Creator Subscription Plans Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/subscription-plans/{plan_id}/archive": {
      "patch": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "Archive Subscription Plan",
        "description": "Archive a subscription plan (soft-delete).\n\nExisting subscribers continue until they cancel. New subscribers can no\nlonger subscribe to an archived plan. Deactivates the Stripe Price.\n\nReturns 404 if the plan does not exist or is not owned by this creator.\nReturns 400 if the plan is already archived.",
        "operationId": "archive_subscription_plan_api_v1_creator_subscription_plans__plan_id__archive_patch",
        "parameters": [
          {
            "name": "plan_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Plan Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/subscribe/{plan_id}": {
      "post": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "Subscribe To Plan",
        "description": "Generate a Stripe Checkout URL for a subscriber to purchase a creator plan.\n\nCreates a Stripe Checkout session (mode=subscription) with:\n- application_fee_percent=20 (AlterLab 20% commission)\n- transfer_data.destination = creator's Stripe Connect account\n- metadata.creator_subscription_plan_id for webhook routing\n\nThe subscriber completes payment on Stripe and is redirected to success_url.\nThe invoice.paid webhook then credits the creator's earnings.\n\nReturns 404 if the plan is not found or not active.\nReturns 409 if the caller is already subscribed to this plan.",
        "operationId": "subscribe_to_plan_api_v1_creator_subscribe__plan_id__post",
        "parameters": [
          {
            "name": "plan_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Plan Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscribeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscribeResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/subscription-metrics": {
      "get": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "Get Subscription Metrics",
        "description": "Return subscription billing metrics for the creator dashboard.\n\nMetrics:\n- subscriber_count: total active + trialing subscribers across all plans\n- mrr_cents: Monthly Recurring Revenue (sum of plan_price * active_subscriber_count)\n- ltv_cents: Total lifetime value paid out (sum of paid payout_events.net_cents)\n- churn_rate_pct: (canceled this month / total) * 100\n- plans: per-plan breakdown with subscriber_count and mrr_cents\n\nRequires the caller to be an onboarded creator.",
        "operationId": "get_subscription_metrics_api_v1_creator_subscription_metrics_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionMetricsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/creator/analytics": {
      "get": {
        "tags": [
          "Creator Subscriptions"
        ],
        "summary": "Get Creator Analytics",
        "description": "Return rich analytics for the creator analytics dashboard.\n\nData:\n- arr_cents: Annual Recurring Revenue (MRR × 12)\n- mrr_cents: current Monthly Recurring Revenue\n- subscriber_count: active + trialing subscribers across all plans\n- churn_rate_pct: (canceled this month / total) × 100\n- ltv_cents: total lifetime net payout received (SQL SUM, not limited)\n- mrr_trend: 12-month MRR time-series [{month: \"YYYY-MM\", mrr_cents}]\n- subscriber_trend: 12-month subscriber growth [{month, new_subscribers, churned, net}]\n- revenue_by_plan: per-plan lifetime earnings + subscriber count + MRR\n- payout_history: last 20 payout events\n\nRequires the caller to be an onboarded creator.",
        "operationId": "get_creator_analytics_api_v1_creator_analytics_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatorAnalyticsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/buyer/subscriptions": {
      "get": {
        "tags": [
          "Buyer Dashboard"
        ],
        "summary": "List My Subscriptions",
        "description": "List creator subscriptions for the authenticated buyer.\n\nReturns all active (and optionally canceled) creator plan subscriptions\nwhere the caller is the subscriber. Joins in plan details and the creator's\nstorefront display name + slug (if the creator has a published storefront).\n\nQuery param:\n  include_canceled=true  — also return canceled/incomplete subscriptions",
        "operationId": "list_my_subscriptions_api_v1_buyer_subscriptions_get",
        "parameters": [
          {
            "name": "include_canceled",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Include canceled subscriptions",
              "default": false,
              "title": "Include Canceled"
            },
            "description": "Include canceled subscriptions"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuyerSubscriptionsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/buyer/purchases": {
      "get": {
        "tags": [
          "Buyer Dashboard"
        ],
        "summary": "List My Purchases",
        "description": "List one-time template purchases for the authenticated buyer.\n\nReturns all TemplateSale rows where buyer_id = current user.\nJoins in template details, the buyer's forked workflow (if any),\nrun count, last-run timestamp/status, and creator storefront info.\n\nRun stats are aggregated in a single SQL round trip using correlated\nsubqueries — no per-row loop queries.",
        "operationId": "list_my_purchases_api_v1_buyer_purchases_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuyerPurchasesResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/buyer/purchases/{sale_id}/runs": {
      "get": {
        "tags": [
          "Buyer Dashboard"
        ],
        "summary": "List Purchase Runs",
        "description": "List workflow runs for a buyer's purchased template.\n\nVerifies that the TemplateSale.buyer_id matches the current user.\nReturns WorkflowRun rows for the buyer's forked workflow, ordered newest-first.\n\nReturns 404 if the sale does not exist or does not belong to the caller.\nReturns 404 if no forked workflow exists for this purchase (template may not yet be run).",
        "operationId": "list_purchase_runs_api_v1_buyer_purchases__sale_id__runs_get",
        "parameters": [
          {
            "name": "sale_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Sale Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BuyerRunsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/secrets": {
      "post": {
        "tags": [
          "Secrets"
        ],
        "summary": "Create Secret",
        "description": "Create a new encrypted secret.",
        "operationId": "create_secret_api_v1_secrets_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Secrets"
        ],
        "summary": "List Secrets",
        "description": "List user's secrets (metadata only — values are never exposed).",
        "operationId": "list_secrets_api_v1_secrets_get",
        "parameters": [
          {
            "name": "integration",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Integration"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/secrets/{secret_id}": {
      "get": {
        "tags": [
          "Secrets"
        ],
        "summary": "Get Secret",
        "description": "Get a secret by ID (metadata only — value is masked).",
        "operationId": "get_secret_api_v1_secrets__secret_id__get",
        "parameters": [
          {
            "name": "secret_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Secret Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Secrets"
        ],
        "summary": "Update Secret",
        "description": "Update a secret's encrypted value.",
        "operationId": "update_secret_api_v1_secrets__secret_id__put",
        "parameters": [
          {
            "name": "secret_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Secret Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SecretResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Secrets"
        ],
        "summary": "Delete Secret",
        "description": "Delete a secret.",
        "operationId": "delete_secret_api_v1_secrets__secret_id__delete",
        "parameters": [
          {
            "name": "secret_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Secret Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat": {
      "post": {
        "tags": [
          "AI Chat"
        ],
        "summary": "Chat",
        "description": "Send a chat message and get a complete AI response.\n\nThe AI assistant can use tools to inspect sites, generate extraction\nschemas, estimate costs, and build workflows. Multi-turn conversations\nare supported via conversation_id.\n\nRate limit: 20 messages per minute.",
        "operationId": "chat_api_v1_chat_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat/stream": {
      "post": {
        "tags": [
          "AI Chat"
        ],
        "summary": "Chat Stream",
        "description": "Send a chat message and receive a streaming SSE response.\n\nEvents:\n  - text: Chunk of assistant text\n  - tool_call: Tool execution started\n  - tool_result: Tool execution completed\n  - action: Structured action (workflow creation, etc.)\n  - error: Error occurred\n  - done: Stream complete (includes conversation_id)\n\nRate limit: 20 messages per minute.",
        "operationId": "chat_stream_api_v1_chat_stream_post",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat/history": {
      "get": {
        "tags": [
          "AI Chat"
        ],
        "summary": "Get Conversation History",
        "description": "Get the message history for a conversation.",
        "operationId": "get_conversation_history_api_v1_chat_history_get",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 64,
              "description": "Conversation ID",
              "title": "Conversation Id"
            },
            "description": "Conversation ID"
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/chat/{conversation_id}": {
      "delete": {
        "tags": [
          "AI Chat"
        ],
        "summary": "Delete Conversation",
        "description": "Delete a conversation from memory.",
        "operationId": "delete_conversation_api_v1_chat__conversation_id__delete",
        "parameters": [
          {
            "name": "conversation_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Conversation Id"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connectors": {
      "post": {
        "tags": [
          "Custom Connectors"
        ],
        "summary": "Upload a custom connector",
        "description": "Upload a connector zip package.\n\nThe zip is validated (static AST scan only — no code execution) and stored\nwith status ``pending``.  An admin must approve it before it can be used.",
        "operationId": "upload_connector_api_v1_connectors_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_upload_connector_api_v1_connectors_post"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectorUploadResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Custom Connectors"
        ],
        "summary": "List user's custom connectors",
        "description": "Return all custom connectors owned by the authenticated user.",
        "operationId": "list_connectors_api_v1_connectors_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectorListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connectors/{slug}/status": {
      "get": {
        "tags": [
          "Custom Connectors"
        ],
        "summary": "Check connector approval status",
        "description": "Return the approval status (and error message if rejected) for a connector.",
        "operationId": "get_connector_status_api_v1_connectors__slug__status_get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectorStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/connectors/{slug}": {
      "delete": {
        "tags": [
          "Custom Connectors"
        ],
        "summary": "Delete a custom connector",
        "description": "Remove a connector and its stored zip.  Irreversible.",
        "operationId": "delete_connector_api_v1_connectors__slug__delete",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists": {
      "post": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Create Contact List",
        "description": "Create a new contact list.\n\nThe caller must set ``processor_notice_accepted=True`` to acknowledge that\nAlterLab is a data processor under GDPR/CCPA and that the owner (data\ncontroller) is responsible for lawful contact collection.",
        "operationId": "create_contact_list_api_v1_contact_lists_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactListCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "List Contact Lists",
        "description": "List contact lists owned by the authenticated user.",
        "operationId": "list_contact_lists_api_v1_contact_lists_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/erasure": {
      "delete": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Erase Contact",
        "description": "Erase a specific email address from ALL contact lists owned by this user.\n\nImplements the GDPR Article 17 right to erasure (right to be forgotten)\nand the CCPA right to deletion.\n\nThe operation is atomic — all matching contact rows are deleted in a\nsingle transaction.  After this call, the email will not appear in any\nof the user's contact lists.",
        "operationId": "erase_contact_api_v1_contact_lists_erasure_delete",
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320,
              "description": "Email address to erase",
              "title": "Email"
            },
            "description": "Email address to erase"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErasureResult"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{list_id}": {
      "get": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Get Contact List",
        "description": "Get a single contact list by ID.",
        "operationId": "get_contact_list_api_v1_contact_lists__list_id__get",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Update Contact List",
        "description": "Update contact list metadata (partial).",
        "operationId": "update_contact_list_api_v1_contact_lists__list_id__patch",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactListUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Delete Contact List",
        "description": "Delete a contact list and all its contacts (CASCADE via FK).",
        "operationId": "delete_contact_list_api_v1_contact_lists__list_id__delete",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{list_id}/contacts": {
      "post": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Add Contact",
        "description": "Add a contact to a list.\n\nEmail is normalised to lowercase.  If the email already exists in this\nlist, returns HTTP 409 Conflict.",
        "operationId": "add_contact_api_v1_contact_lists__list_id__contacts_post",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "List Contacts",
        "description": "List contacts in a contact list (paginated).",
        "operationId": "list_contacts_api_v1_contact_lists__list_id__contacts_get",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1,
              "title": "Page"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 100
                },
                {
                  "type": "null"
                }
              ],
              "title": "Q"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactListContentsResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{list_id}/contacts/{contact_id}": {
      "patch": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Update Contact",
        "description": "Update a contact (partial).",
        "operationId": "update_contact_api_v1_contact_lists__list_id__contacts__contact_id__patch",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Contact Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{list_id}/export": {
      "get": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Export Contacts",
        "description": "Export contacts as CSV including data provenance fields.\n\nThe provenance fields (data_source, source_url, source_workflow_id,\nconsent_basis) are included in every export to satisfy CCPA data subject\ndisclosure requirements and to support audit trails.",
        "operationId": "export_contacts_api_v1_contact_lists__list_id__export_get",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/{list_id}/import": {
      "post": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Import contacts from a CSV file",
        "description": "Import contacts from a CSV file into a contact list.\n\nRules:\n- The CSV MUST have an ``email`` header column.\n- Uploads exceeding 10 MB are rejected with HTTP 413 before being read into\n  memory; this guard applies even for chunked-encoded uploads.\n- Duplicate emails (already in the list, or repeated within the CSV) are\n  silently skipped and counted in ``skipped``.\n- Rows that fail validation (invalid status, malformed email, etc.) are\n  counted in ``errors``; up to 10 sample error messages are returned.\n- A maximum of 10,000 rows per import is enforced; excess rows are ignored.\n- All emails are normalised to lowercase before insert (matching the DB\n  UNIQUE constraint on lower(email)).\n\nUses FlexibleUser so that both API key and JWT Bearer (dashboard) callers\nare accepted — consistent with all other endpoints in this router.",
        "operationId": "import_contacts_csv_api_v1_contact_lists__list_id__import_post",
        "parameters": [
          {
            "name": "list_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "List Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_import_contacts_csv_api_v1_contact_lists__list_id__import_post"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CsvImportResult"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/contact-lists/policy": {
      "get": {
        "tags": [
          "Contact Lists"
        ],
        "summary": "Get Processor Policy",
        "description": "Return AlterLab's data processor policy for contact lists.\n\nNo authentication required — this is a public disclosure endpoint.\nThe policy text describes AlterLab's role as a data processor under\nGDPR/CCPA and the responsibilities of the list owner (data controller).",
        "operationId": "get_processor_policy_api_v1_contact_lists_policy_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Get Processor Policy Api V1 Contact Lists Policy Get"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/privacy/opt-out": {
      "post": {
        "tags": [
          "Privacy"
        ],
        "summary": "Request removal from enrichment results",
        "description": "Submit a privacy opt-out request to prevent your email address from appearing in enrichment results. This action is permanent. No account is required.",
        "operationId": "privacy_opt_out_api_v1_privacy_opt_out_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OptOutRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OptOutResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{org_id}/workflows": {
      "get": {
        "tags": [
          "Workspaces"
        ],
        "summary": "List workflows shared to a workspace",
        "description": "Return workflows whose ``organization_id`` equals ``org_id``.\n\nCaller must be at least a member of the organization.",
        "operationId": "list_shared_workflows_api_v1_workspaces__org_id__workflows_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SharedWorkflowListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{org_id}/secrets": {
      "get": {
        "tags": [
          "Workspaces"
        ],
        "summary": "List secrets shared to a workspace (masked preview only)",
        "description": "Return secrets whose ``organization_id`` equals ``org_id``.\n\nOnly the pre-computed ``masked_preview`` is returned — the encrypted value\nis never exposed through this endpoint.\n\nCaller must be at least a member of the organization.",
        "operationId": "list_shared_secrets_api_v1_workspaces__org_id__secrets_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SharedSecretListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{org_id}/contact-lists": {
      "get": {
        "tags": [
          "Workspaces"
        ],
        "summary": "List contact lists shared to a workspace",
        "description": "Return contact lists whose ``organization_id`` equals ``org_id``.\n\nCaller must be at least a member of the organization.",
        "operationId": "list_shared_contact_lists_api_v1_workspaces__org_id__contact_lists_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50,
              "title": "Limit"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0,
              "title": "Offset"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SharedContactListListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{org_id}/resources/{resource_type}/{resource_id}/share": {
      "post": {
        "tags": [
          "Workspaces"
        ],
        "summary": "Share a personal resource to a workspace",
        "description": "Set ``organization_id`` on a resource to share it with an org workspace.\n\nThe caller must:\n- Be at least an admin of the target organization\n- Own the resource being shared (``user_id = caller``)\n\nOn success, a ``WorkspaceActivityLog`` entry is written.",
        "operationId": "share_resource_api_v1_workspaces__org_id__resources__resource_type___resource_id__share_post",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "resource_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Resource Type"
            }
          },
          {
            "name": "resource_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Resource Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShareResourceResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Workspaces"
        ],
        "summary": "Unshare a resource from a workspace",
        "description": "Clear ``organization_id`` on a resource to remove it from an org workspace.\n\nThe caller must:\n- Be at least an admin of the target organization\n- Own the resource being unshared (``user_id = caller``)\n\nOn success, a ``WorkspaceActivityLog`` entry is written.",
        "operationId": "unshare_resource_api_v1_workspaces__org_id__resources__resource_type___resource_id__share_delete",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "resource_type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Resource Type"
            }
          },
          {
            "name": "resource_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Resource Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnshareResourceResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/workspaces/{org_id}/activity": {
      "get": {
        "tags": [
          "Workspaces"
        ],
        "summary": "Get workspace activity feed",
        "description": "Return a paginated activity feed for the given org workspace.\n\nLists all ``WorkspaceActivityLog`` rows for ``org_id``, newest first.\nThe caller must be at least a member of the organization.\n\nArgs:\n    org_id: UUID of the organization whose activity feed to retrieve.\n    limit: Maximum number of items to return (1–200, default 50).\n    offset: Number of items to skip for pagination (default 0).",
        "operationId": "get_workspace_activity_api_v1_workspaces__org_id__activity_get",
        "parameters": [
          {
            "name": "org_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Org Id"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "description": "Page size",
              "default": 50,
              "title": "Limit"
            },
            "description": "Page size"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Page offset",
              "default": 0,
              "title": "Offset"
            },
            "description": "Page offset"
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityFeedResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates": {
      "get": {
        "tags": [
          "Scrape Templates"
        ],
        "summary": "List public scrape templates",
        "description": "Returns a paginated list of public scrape templates.  No authentication required.",
        "operationId": "list_templates_api_v1_templates_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-based)",
              "default": 1,
              "title": "Page"
            },
            "description": "Page number (1-based)"
          },
          {
            "name": "page_size",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Items per page",
              "default": 20,
              "title": "Page Size"
            },
            "description": "Items per page"
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by tag",
              "title": "Tag"
            },
            "description": "Filter by tag"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeTemplateListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/templates/{slug}": {
      "get": {
        "tags": [
          "Scrape Templates"
        ],
        "summary": "Get a scrape template by slug",
        "description": "Returns a single public scrape template.  No authentication required.",
        "operationId": "get_template_api_v1_templates__slug__get",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScrapeTemplateDetailResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extract/templates": {
      "get": {
        "tags": [
          "Extraction Templates"
        ],
        "summary": "List extraction templates",
        "description": "Returns all built-in extraction templates plus the authenticated user's saved custom templates. Built-in templates are always present and cannot be deleted.",
        "operationId": "list_templates_api_v1_extract_templates_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Extraction Templates"
        ],
        "summary": "Save a custom extraction template",
        "description": "Save a custom JSON Schema as a named extraction template. The saved template can then be referenced when running extractions by supplying its ID or by passing the schema directly.",
        "operationId": "save_template_api_v1_extract_templates_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveTemplateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SaveTemplateResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/extract/templates/{template_id}": {
      "get": {
        "tags": [
          "Extraction Templates"
        ],
        "summary": "Get a user template by ID",
        "description": "Retrieve a single user-saved extraction template by its UUID.",
        "operationId": "get_template_api_v1_extract_templates__template_id__get",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateItem"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Extraction Templates"
        ],
        "summary": "Delete a user template",
        "description": "Delete a user-saved extraction template by its UUID.",
        "operationId": "delete_template_api_v1_extract_templates__template_id__delete",
        "parameters": [
          {
            "name": "template_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Template Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user/llm-keys/openrouter/exchange": {
      "post": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "Exchange OpenRouter OAuth PKCE code for an API key",
        "description": "Complete the OpenRouter OAuth PKCE flow by exchanging an authorization code for an API key. The key is encrypted at rest and stored identically to a manually-pasted key. No app registration or client ID is required.",
        "operationId": "exchange_openrouter_code_api_v1_user_llm_keys_openrouter_exchange_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OpenRouterExchangeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserLLMKeyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user/llm-keys": {
      "post": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "Register a BYOK LLM API key",
        "description": "Encrypt and store a new LLM provider API key. The raw key is encrypted at rest immediately and is never returned. An async validation call is made to the provider after storage. Duplicate (provider, user) pairs return HTTP 409.",
        "operationId": "register_llm_key_api_v1_user_llm_keys_post",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserLLMKeyCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserLLMKeyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "List BYOK LLM API keys",
        "description": "List all active (non-deleted) BYOK LLM keys for the authenticated user.",
        "operationId": "list_llm_keys_api_v1_user_llm_keys_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/UserLLMKeyResponse"
                  },
                  "title": "Response List Llm Keys Api V1 User Llm Keys Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user/llm-keys/{key_id}": {
      "delete": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "Delete a BYOK LLM API key",
        "description": "Soft-delete a BYOK LLM key. The key is marked as deleted and will no longer be used for extraction. Returns 404 if the key does not exist or belongs to another user.",
        "operationId": "delete_llm_key_api_v1_user_llm_keys__key_id__delete",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Key Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "Update a BYOK LLM API key",
        "description": "Update the alias and/or replace the key entirely. If ``raw_key`` is provided, it replaces the stored encrypted key. At least one field must be non-null.",
        "operationId": "update_llm_key_api_v1_user_llm_keys__key_id__put",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Key Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserLLMKeyUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserLLMKeyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user/llm-keys/{key_id}/validate": {
      "post": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "Validate a BYOK LLM API key",
        "description": "Re-validate an existing BYOK LLM key by making a lightweight API call to the provider. Updates ``is_valid`` and ``last_validated_at`` regardless of outcome. Returns the updated key record.",
        "operationId": "validate_llm_key_api_v1_user_llm_keys__key_id__validate_post",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Key Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserLLMKeyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/user/llm-keys/{key_id}/models": {
      "get": {
        "tags": [
          "BYOK LLM Keys"
        ],
        "summary": "List available models for a BYOK LLM key",
        "description": "Fetch the full model catalog available under the user's LLM provider key. Results are cached in Redis for 1 hour — provider model lists change infrequently. Returns 404 if the key is not owned by the user. Returns 502 if the provider is unreachable or rejects the key.",
        "operationId": "list_models_for_key_api_v1_user_llm_keys__key_id__models_get",
        "parameters": [
          {
            "name": "key_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "title": "Key Id"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProviderModel"
                  },
                  "title": "Response List Models For Key Api V1 User Llm Keys  Key Id  Models Get"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/beta-features": {
      "get": {
        "tags": [
          "Beta Features"
        ],
        "summary": "List available beta features",
        "description": "Returns all features with status 'beta' or 'ga'. Each item includes an ``enabled`` field indicating whether the requesting user has access to the feature. GA (generally available) features return ``enabled: true`` for all callers, including anonymous ones — they are permanently enabled for everyone. Beta features require explicit opt-in: authenticated users see their real opt-in state, anonymous callers receive ``enabled: false``. Hidden features are never returned.",
        "operationId": "list_beta_features_api_v1_beta_features_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BetaFeatureListResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-beta-management": true
      }
    },
    "/api/v1/beta-features/my": {
      "get": {
        "tags": [
          "Beta Features"
        ],
        "summary": "List my enabled beta features",
        "description": "Returns the slugs of all beta and GA features the authenticated user has access to. Intended for lightweight frontend checks — cheaper than fetching the full feature list.",
        "operationId": "list_my_beta_features_api_v1_beta_features_my_get",
        "parameters": [
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BetaFeatureMyResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-beta-management": true
      }
    },
    "/api/v1/beta-features/{slug}/enable": {
      "post": {
        "tags": [
          "Beta Features"
        ],
        "summary": "Enable a beta feature",
        "description": "Opt in to a beta feature. Returns 200 if already enabled (idempotent). Returns 404 if the feature does not exist. Returns 400 if the feature is 'hidden' — hidden features cannot be opted into. Rate limited to 10 combined enable/disable operations per minute per user.",
        "operationId": "enable_beta_feature_api_v1_beta_features__slug__enable_post",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BetaFeatureToggleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-beta-management": true
      }
    },
    "/api/v1/beta-features/{slug}/disable": {
      "post": {
        "tags": [
          "Beta Features"
        ],
        "summary": "Disable a beta feature",
        "description": "Opt out of a beta feature. Returns 200 even if the feature was not enabled (idempotent). Returns 404 if the feature does not exist. Returns 400 if the feature is 'ga' — GA features cannot be disabled. Rate limited to 10 combined enable/disable operations per minute per user.",
        "operationId": "disable_beta_feature_api_v1_beta_features__slug__disable_post",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Slug"
            }
          },
          {
            "name": "x-api-key",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "X-Api-Key"
            }
          },
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Authorization"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BetaFeatureToggleResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        },
        "x-beta-management": true
      }
    },
    "/api/v1/agent-onboarding/setup-intent": {
      "post": {
        "tags": [
          "Agent Onboarding"
        ],
        "summary": "Create an anonymous Stripe SetupIntent for agent onboarding",
        "description": "Creates a Stripe Customer and SetupIntent for a bare email address, with no pre-existing AlterLab account required. No User row is created at this step — only a Stripe Customer keyed by the pending email. Confirm the SetupIntent client-side with Stripe.js, then call POST /confirm to provision the account and receive an API key.",
        "operationId": "create_agent_setup_intent_api_v1_agent_onboarding_setup_intent_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentSetupIntentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentSetupIntentResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent-onboarding/confirm": {
      "post": {
        "tags": [
          "Agent Onboarding"
        ],
        "summary": "Confirm a SetupIntent and issue a self-serve API key",
        "description": "Verifies the SetupIntent succeeded (re-checked live against the Stripe API, never trusted from client input), then atomically provisions a User, personal Organization, and a scoped API key with a default spend limit. The plaintext API key is returned exactly once.",
        "operationId": "confirm_agent_setup_intent_api_v1_agent_onboarding_confirm_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentConfirmResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/feedback": {
      "post": {
        "tags": [
          "Agent Feedback",
          "Agent Feedback"
        ],
        "summary": "Submit Agent Feedback",
        "description": "POST /api/v1/agent/feedback — submit a public agent feedback report. No authentication required.\n\nRate limited to 5 requests/minute per client IP. Text fields are\nscrubbed for common PII patterns and truncated before persistence.",
        "operationId": "submit_agent_feedback_api_v1_agent_feedback_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentFeedbackReportRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentFeedbackReportResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/feedback/{cluster_key}": {
      "get": {
        "tags": [
          "Agent Feedback",
          "Agent Feedback"
        ],
        "summary": "Get Agent Feedback Status",
        "description": "GET /api/v1/agent/feedback/{cluster_key} — look up aggregation-safe status for a report by its cluster key.\n\nNo authentication required. Never echoes back submitted text.",
        "operationId": "get_agent_feedback_status_api_v1_agent_feedback__cluster_key__get",
        "parameters": [
          {
            "name": "cluster_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Cluster Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentFeedbackStatusResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/issues": {
      "get": {
        "tags": [
          "Agent Feedback",
          "Agent Feedback"
        ],
        "summary": "List Agent Issues",
        "description": "GET /api/v1/agent/issues — browse aggregated, publicly-safe agent feedback patterns.\n\nOnly clusters with report_count >= 3 are returned. No raw URLs, PII,\nor individual request data are ever included — the aggregation floor\nis enforced in SQL (HAVING), not filtered after fetch.",
        "operationId": "list_agent_issues_api_v1_agent_issues_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentIssuesListResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/agent/issues/{cluster_key}/vote": {
      "post": {
        "tags": [
          "Agent Feedback",
          "Agent Feedback"
        ],
        "summary": "Vote Agent Issue",
        "description": "Confirm ('I hit this too') a public issue cluster.\n\nNo authentication required. Rate limited by client IP. Deduped per\nagent/session via a hashed identifier — repeat votes from the same\nvoter return status='already_voted' idempotently rather than erroring.",
        "operationId": "vote_agent_issue_api_v1_agent_issues__cluster_key__vote_post",
        "parameters": [
          {
            "name": "cluster_key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Cluster Key"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AgentFeedbackVoteResponse"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "APIKeyCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Name for the API key"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "APIKeyCreate",
        "description": "API key creation request."
      },
      "APIKeyLimitSummary": {
        "properties": {
          "budget_limit_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget Limit Microcents"
          },
          "request_limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Limit"
          },
          "reset_period": {
            "type": "string",
            "title": "Reset Period",
            "default": "monthly"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          },
          "current_spend_microcents": {
            "type": "integer",
            "title": "Current Spend Microcents",
            "default": 0
          },
          "current_request_count": {
            "type": "integer",
            "title": "Current Request Count",
            "default": 0
          },
          "budget_percent_used": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget Percent Used"
          },
          "requests_percent_used": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requests Percent Used"
          },
          "resets_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resets At"
          }
        },
        "type": "object",
        "title": "APIKeyLimitSummary",
        "description": "Inline limit summary returned with each key in the list."
      },
      "APIKeyListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/APIKeyResponse"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "offset": {
            "type": "integer",
            "title": "Offset"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "title": "APIKeyListResponse",
        "description": "Paginated API key list response."
      },
      "APIKeyRename": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "New name for the API key"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "APIKeyRename",
        "description": "API key rename request."
      },
      "APIKeyResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "key_prefix": {
            "type": "string",
            "title": "Key Prefix"
          },
          "key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Scopes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "requests": {
            "type": "integer",
            "title": "Requests",
            "default": 0
          },
          "is_legacy": {
            "type": "boolean",
            "title": "Is Legacy",
            "default": false
          },
          "spend_microcents": {
            "type": "integer",
            "title": "Spend Microcents",
            "default": 0
          },
          "limits": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/APIKeyLimitSummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "key_type": {
            "type": "string",
            "title": "Key Type",
            "default": "user"
          },
          "ip_allowlist": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Allowlist"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "key_prefix",
          "scopes",
          "created_at"
        ],
        "title": "APIKeyResponse",
        "description": "API key response."
      },
      "AccessLogEntry": {
        "properties": {
          "timestamp": {
            "type": "string",
            "title": "Timestamp",
            "description": "ISO 8601 timestamp"
          },
          "ip_hash": {
            "type": "string",
            "title": "Ip Hash",
            "description": "SHA-256 hash of IP (first 16 chars)"
          },
          "ip_display": {
            "type": "string",
            "title": "Ip Display",
            "description": "Raw IP if within 1-hour cache, otherwise truncated hash"
          },
          "source": {
            "type": "string",
            "title": "Source",
            "description": "Access source: api, playground, sdk"
          },
          "geo_city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Geo City",
            "description": "City from geo lookup"
          },
          "geo_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Geo Country",
            "description": "Country from geo lookup"
          },
          "api_key_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Api Key Id",
            "description": "Which API key was used"
          }
        },
        "type": "object",
        "required": [
          "timestamp",
          "ip_hash",
          "ip_display",
          "source"
        ],
        "title": "AccessLogEntry",
        "description": "A single entry in the session access log."
      },
      "AccessLogResponse": {
        "properties": {
          "entries": {
            "items": {
              "$ref": "#/components/schemas/AccessLogEntry"
            },
            "type": "array",
            "title": "Entries"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "known_ip_count": {
            "type": "integer",
            "title": "Known Ip Count",
            "description": "Number of distinct known IPs for this user"
          }
        },
        "type": "object",
        "required": [
          "entries",
          "total",
          "known_ip_count"
        ],
        "title": "AccessLogResponse",
        "description": "Response for session access log endpoint."
      },
      "AccountSecurityResponse": {
        "properties": {
          "primary_method": {
            "type": "string",
            "title": "Primary Method"
          },
          "has_password": {
            "type": "boolean",
            "title": "Has Password"
          },
          "linked_providers": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Linked Providers"
          },
          "can_add_password": {
            "type": "boolean",
            "title": "Can Add Password"
          },
          "email_verified": {
            "type": "boolean",
            "title": "Email Verified"
          }
        },
        "type": "object",
        "required": [
          "primary_method",
          "has_password",
          "linked_providers",
          "can_add_password",
          "email_verified"
        ],
        "title": "AccountSecurityResponse",
        "description": "Response with account security overview."
      },
      "AccountSpendLimitResponse": {
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "limits": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpendLimitStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "has_limits": {
            "type": "boolean",
            "title": "Has Limits",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "user_id"
        ],
        "title": "AccountSpendLimitResponse",
        "description": "Response for account-level limit status."
      },
      "ActionResult": {
        "properties": {
          "index": {
            "type": "integer",
            "title": "Index",
            "description": "Action index in the sequence (0-based)"
          },
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Action type that was executed"
          },
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "Whether the action completed successfully"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message if action failed"
          },
          "result": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result",
            "description": "Return value (for evaluate actions)"
          },
          "screenshot": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Screenshot",
            "description": "Base64-encoded screenshot (for screenshot actions)"
          }
        },
        "type": "object",
        "required": [
          "index",
          "type",
          "success"
        ],
        "title": "ActionResult",
        "description": "Result of a single browser action execution."
      },
      "ActiveNotificationListResponse": {
        "properties": {
          "notifications": {
            "items": {
              "$ref": "#/components/schemas/ActiveNotificationResponse"
            },
            "type": "array",
            "title": "Notifications"
          }
        },
        "type": "object",
        "required": [
          "notifications"
        ],
        "title": "ActiveNotificationListResponse"
      },
      "ActiveNotificationResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "type": {
            "type": "string",
            "title": "Type"
          },
          "variant": {
            "type": "string",
            "title": "Variant"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "action_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action Url"
          },
          "action_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action Label"
          },
          "dismiss_delay": {
            "type": "integer",
            "title": "Dismiss Delay"
          },
          "priority": {
            "type": "integer",
            "title": "Priority"
          }
        },
        "type": "object",
        "required": [
          "id",
          "type",
          "variant",
          "title",
          "body",
          "dismiss_delay",
          "priority"
        ],
        "title": "ActiveNotificationResponse",
        "description": "Slim response for user-facing notification display."
      },
      "ActivityFeedItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "actor_user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actor User Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "resource_type": {
            "type": "string",
            "title": "Resource Type"
          },
          "resource_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Id"
          },
          "resource_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Name"
          },
          "details": {
            "additionalProperties": true,
            "type": "object",
            "title": "Details"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "organization_id",
          "action",
          "resource_type",
          "created_at"
        ],
        "title": "ActivityFeedItem",
        "description": "A single entry in the org workspace activity feed.\n\n``actor_user_id`` is nullable because the actor may have been deleted;\nthe row is preserved with a NULL FK (ON DELETE SET NULL on the DB column)."
      },
      "ActivityFeedResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/ActivityFeedItem"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "offset": {
            "type": "integer",
            "title": "Offset"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset"
        ],
        "title": "ActivityFeedResponse",
        "description": "Paginated response for the workspace activity feed endpoint."
      },
      "AdResultResponse": {
        "properties": {
          "position": {
            "type": "integer",
            "title": "Position",
            "description": "1-indexed position within the slot"
          },
          "slot": {
            "type": "string",
            "title": "Slot",
            "description": "Ad slot: 'top' (#tads) or 'bottom' (#bottomads)"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title",
            "description": "Ad headline text"
          },
          "display_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Url",
            "description": "URL as displayed in the ad (breadcrumb-style)"
          },
          "destination_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Destination Url",
            "description": "Unwrapped destination URL of the ad"
          },
          "ad_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Label",
            "description": "Ad label text (e.g. 'Sponsored')"
          },
          "ad_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Id",
            "description": "Batchexecute ad identifier extracted from the SERP DOM. Sourced from the 'ai=' query parameter of the aclk URL in the ad anchor's 'data-rw' attribute (e.g. 'DChcSEwjn...'). Used to cross-reference ads across searches and track specific ad placements over time."
          },
          "advertiser_link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Link",
            "description": "Advertiser transparency URL (adstransparency.google.com/advertiser/AR...). Extract the AR-format ID from this URL for advertiser lookup."
          },
          "advertiser_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Name",
            "description": "Advertiser name extracted from ad DOM or transparency data"
          },
          "advertiser_domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Domain",
            "description": "Advertiser domain (from data-dtld attribute or destination URL)"
          },
          "advertiser_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Country",
            "description": "Advertiser country from Google Ads Transparency Center. Populated by BatchExecuteFetcher after SERP fetch for tenant jobs. Requires ATC fallback via advertiser_link AR-format ID."
          },
          "sitelinks": {
            "items": {
              "$ref": "#/components/schemas/SitelinkResponse"
            },
            "type": "array",
            "title": "Sitelinks",
            "description": "Sitelink extensions shown under this ad. Each entry is a distinct landing page link within the same advertiser's ad unit."
          },
          "advertiser_profile": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Profile",
            "description": "Advertiser profile fetched from Google Ads Transparency Center. Populated by AdvertiserTransparencyFetcher after parsing, not during parsing."
          }
        },
        "type": "object",
        "required": [
          "position",
          "slot"
        ],
        "title": "AdResultResponse",
        "description": "A paid text advertisement from Google SERP (top or bottom slot)."
      },
      "AddPasswordRequest": {
        "properties": {
          "password": {
            "type": "string",
            "title": "Password"
          }
        },
        "type": "object",
        "required": [
          "password"
        ],
        "title": "AddPasswordRequest",
        "description": "Request to add password to OAuth-only account."
      },
      "AddPasswordResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "AddPasswordResponse",
        "description": "Response for add password operation."
      },
      "AddPaymentMethodRequest": {
        "properties": {
          "payment_method_id": {
            "type": "string",
            "title": "Payment Method Id"
          }
        },
        "type": "object",
        "required": [
          "payment_method_id"
        ],
        "title": "AddPaymentMethodRequest",
        "description": "Request to add a new payment method."
      },
      "AdvancedOptions": {
        "properties": {
          "render_js": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string",
                "const": "auto"
              }
            ],
            "title": "Render Js",
            "description": "Render JavaScript using headless browser (forces Tier 4 minimum). Set to \"auto\" for smart detection: probes each page and only renders JS-heavy pages with browser, using fast HTTP for static pages. Saves 30-60% on mixed sites.",
            "default": false
          },
          "screenshot": {
            "type": "boolean",
            "title": "Screenshot",
            "description": "Capture full-page screenshot (+$0.0002, requires render_js)",
            "default": false
          },
          "markdown": {
            "type": "boolean",
            "title": "Markdown",
            "description": "Extract content as Markdown (free)",
            "default": false
          },
          "generate_pdf": {
            "type": "boolean",
            "title": "Generate Pdf",
            "description": "Generate PDF of rendered page (+$0.0004, requires render_js)",
            "default": false
          },
          "ocr": {
            "type": "boolean",
            "title": "Ocr",
            "description": "Extract text from images using OCR (+$0.001)",
            "default": false
          },
          "use_proxy": {
            "type": "boolean",
            "title": "Use Proxy",
            "description": "Route request through premium proxy (+$0.0002)",
            "default": false
          },
          "use_own_proxy": {
            "type": "boolean",
            "title": "Use Own Proxy",
            "description": "Use your own integrated proxy instead of system proxy ($0.0008/request)",
            "default": false
          },
          "use_system_proxy": {
            "type": "boolean",
            "title": "Use System Proxy",
            "description": "Override your default proxy integration and use AlterLab's system proxy instead",
            "default": false
          },
          "proxy_integration_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Integration Id",
            "description": "Specific proxy integration ID to use (requires use_own_proxy=true)"
          },
          "proxy_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Country",
            "description": "Preferred proxy country code (e.g., 'US', 'DE') for geo-targeting"
          },
          "wait_condition": {
            "type": "string",
            "title": "Wait Condition",
            "description": "Wait condition for JS rendering (domcontentloaded|networkidle|load)",
            "default": "networkidle"
          },
          "remove_cookie_banners": {
            "type": "boolean",
            "title": "Remove Cookie Banners",
            "description": "Remove cookie consent banners from HTML before content extraction (free, enabled by default)",
            "default": true
          },
          "include_iframes": {
            "type": "boolean",
            "title": "Include Iframes",
            "description": "Inline iframe content into the main document (free, requires render_js). Same-origin iframes are read directly; cross-origin iframes are marked but not fetched.",
            "default": false
          },
          "flatten_shadow_dom": {
            "type": "boolean",
            "title": "Flatten Shadow Dom",
            "description": "Flatten Shadow DOM roots into regular DOM for extraction (free, requires render_js). Web Components with shadow roots become visible in the serialized HTML.",
            "default": false
          },
          "block_images": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Block Images",
            "description": "Skip image downloads during browser rendering to reduce proxy bandwidth. When true, the browser aborts image requests — <img> src URLs remain in the DOM so HTML and text extraction are unaffected, but image bytes are not downloaded. When false, all images are downloaded (higher bandwidth, needed for visual accuracy). When null (default), the per-domain playbook setting is used. Most domains default to blocking images (true) to save bandwidth. E-commerce domains like amazon.com default to false because their anti-bot systems monitor resource loading patterns — browsers that never request images are more likely to be flagged as bots. Note: screenshot and generate_pdf always override this to false regardless of the value passed — images are required for accurate visual output."
          },
          "scroll_to_load": {
            "type": "boolean",
            "title": "Scroll To Load",
            "description": "Scroll page to trigger lazy-loaded content (requires render_js). Performs explicit viewport-height scrolls to load dynamic content. Adds ~2-3s latency.",
            "default": false
          },
          "scroll_count": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 1.0,
            "title": "Scroll Count",
            "description": "Number of scroll iterations when scroll_to_load is enabled (1-10, default 3).",
            "default": 3
          },
          "section_filter": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SectionFilter"
              },
              {
                "type": "null"
              }
            ],
            "description": "Filter options for json_v2 section tree output. Only applies when 'json_v2' is in the formats list. Controls which sections and content blocks are included in the response."
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "Reference to a stored SessionIntegration. Injects stored cookies/headers for authenticated scraping."
          },
          "cookies": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookies",
            "description": "Inline cookies for one-off authenticated scraping (not stored). Mutually exclusive with session_id."
          },
          "session_headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Headers",
            "description": "Inline auth headers (e.g. Authorization: Bearer). Merged with session headers if session_id is also resolving headers."
          },
          "sticky_session": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 128
              },
              {
                "type": "null"
              }
            ],
            "title": "Sticky Session",
            "description": "Customer-facing sticky-session handle. Two separate /scrape calls that pass the same sticky_session value reuse the cookies captured on the first call (see captured_cookies in the response) for the handle's TTL, and target the SAME exit IP on a best-effort basis. Note the exit IP is only guaranteed to hold for the upstream residential-session window (~10 minutes) — for longer TTLs the shared cookie jar persists but the exit IP may rotate. Enables stateful multi-request flows — e.g. request 1 loads a page, request 2 fetches the captcha/image that appeared using request 1's cookie jar (and, within ~10 min, the same IP). Requires a paid plan (growth tier or above). Alphanumeric, '-' and '_' only, max 128 chars."
          },
          "sticky_session_ttl": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 7200.0,
                "minimum": 300.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Sticky Session Ttl",
            "description": "Sticky-session lifetime in seconds (300–7200, default 1800). This governs how long the captured cookie jar bound to sticky_session is retained; after it the handle resolves to a fresh jar. The exit-IP pin is separate and shorter — it holds only for the upstream residential-session window (~10 minutes), so a TTL above that keeps the cookie jar alive while the exit IP may rotate. Ignored unless sticky_session is set."
          },
          "actions": {
            "anyOf": [
              {
                "items": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/WaitAction"
                    },
                    {
                      "$ref": "#/components/schemas/WaitForAction"
                    },
                    {
                      "$ref": "#/components/schemas/ClickAction"
                    },
                    {
                      "$ref": "#/components/schemas/FillAction"
                    },
                    {
                      "$ref": "#/components/schemas/PressAction"
                    },
                    {
                      "$ref": "#/components/schemas/ScrollAction"
                    },
                    {
                      "$ref": "#/components/schemas/InfiniteScrollAction"
                    },
                    {
                      "$ref": "#/components/schemas/ScreenshotAction"
                    },
                    {
                      "$ref": "#/components/schemas/EvaluateAction"
                    }
                  ]
                },
                "type": "array",
                "maxItems": 20
              },
              {
                "type": "null"
              }
            ],
            "title": "Actions",
            "description": "Browser automation actions to execute after page load (max 20). Requires render_js=true. Actions execute sequentially; failed actions are skipped (don't abort the sequence). Results returned in action_results."
          }
        },
        "type": "object",
        "title": "AdvancedOptions",
        "description": "Advanced scraping options with add-on costs (in microcents).\n\nAdd-on Costs (see ADDON_MICROCENTS in pricing.py):\n- render_js: Forces Tier 4 ($0.004) — no extra surcharge\n- screenshot: +$0.0002 (200 microcents, requires render_js)\n- generate_pdf: +$0.0004 (400 microcents, requires render_js)\n- ocr: +$0.001 (1000 microcents)\n- use_proxy: +$0.0002 (200 microcents)\n- markdown: Free\n- wait_condition: Free"
      },
      "AdvertiserChange": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain",
            "description": "Advertiser domain"
          },
          "change_type": {
            "type": "string",
            "title": "Change Type",
            "description": "Type of change: 'new', 'dropped', 'position_up', 'position_down'"
          },
          "previous_position": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Position",
            "description": "Previous ad position (if applicable)"
          },
          "current_position": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Position",
            "description": "Current ad position (if applicable)"
          },
          "first_seen": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Seen",
            "description": "When this advertiser first appeared"
          },
          "last_seen": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Seen",
            "description": "When this advertiser was last seen"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "change_type"
        ],
        "title": "AdvertiserChange",
        "description": "A single advertiser change between snapshots."
      },
      "AffiliateApplyRequest": {
        "properties": {
          "notes": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes",
            "description": "Optional message to the admin (e.g. how you plan to promote AlterLab)."
          }
        },
        "type": "object",
        "title": "AffiliateApplyRequest",
        "description": "Request body for POST /affiliates/apply."
      },
      "AffiliateApplyResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "referral_code": {
            "type": "string",
            "title": "Referral Code"
          },
          "referral_link": {
            "type": "string",
            "title": "Referral Link"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "commission_rate": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Commission Rate"
          },
          "max_commission_microcents": {
            "type": "integer",
            "title": "Max Commission Microcents",
            "description": "Per-referral commission cap in microcents (10,000,000 = $10)"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "title": "Joined At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "referral_code",
          "referral_link",
          "status",
          "commission_rate",
          "max_commission_microcents",
          "joined_at"
        ],
        "title": "AffiliateApplyResponse",
        "description": "Response for POST /affiliates/apply."
      },
      "AffiliateClickRequest": {
        "properties": {
          "referral_code": {
            "type": "string",
            "maxLength": 50,
            "minLength": 1,
            "title": "Referral Code",
            "description": "Affiliate referral code from the ref= URL parameter (e.g. REF-ABCD1234)."
          },
          "landing_page": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Landing Page",
            "description": "URL path + query string of the landing page (e.g. /?ref=REF-ABCD1234)."
          }
        },
        "type": "object",
        "required": [
          "referral_code"
        ],
        "title": "AffiliateClickRequest",
        "description": "Request body for POST /affiliates/track/click.\n\nUnauthenticated endpoint — called when a visitor arrives via a referral link.\nThe referral code identifies which affiliate to credit."
      },
      "AffiliateClickResponse": {
        "properties": {
          "recorded": {
            "type": "boolean",
            "title": "Recorded",
            "description": "True if a new click row was inserted. False if deduplicated (same visitor already counted within the 24-hour window)."
          }
        },
        "type": "object",
        "required": [
          "recorded"
        ],
        "title": "AffiliateClickResponse",
        "description": "Response for POST /affiliates/track/click."
      },
      "AffiliateConversionItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "commission_microcents": {
            "type": "integer",
            "title": "Commission Microcents",
            "description": "Commission earned in microcents"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Conversion status: pending, approved, paid, or reversed"
          },
          "paid_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paid At",
            "description": "Timestamp when commission was paid out"
          },
          "referred_user_token": {
            "type": "string",
            "title": "Referred User Token",
            "description": "Anonymized referred user identifier (first 8 chars of their UUID)"
          }
        },
        "type": "object",
        "required": [
          "id",
          "created_at",
          "commission_microcents",
          "status",
          "referred_user_token"
        ],
        "title": "AffiliateConversionItem",
        "description": "Single conversion record in the affiliate conversions list.\n\nThe referred user's identity is anonymized to the first 8 characters of\ntheir UUID (e.g., 'a1b2c3d4'). The full UUID is never exposed to the\naffiliate."
      },
      "AffiliateConversionsListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/AffiliateConversionItem"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "page_size"
        ],
        "title": "AffiliateConversionsListResponse",
        "description": "Response for GET /affiliates/me/conversions — paginated conversion history."
      },
      "AffiliateProfileResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "referral_code": {
            "type": "string",
            "title": "Referral Code"
          },
          "referral_link": {
            "type": "string",
            "title": "Referral Link",
            "description": "Full referral URL: https://alterlab.io/?ref=CODE"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "commission_rate": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Commission Rate"
          },
          "max_commission_microcents": {
            "type": "integer",
            "title": "Max Commission Microcents",
            "description": "Per-referral commission cap in microcents (10,000,000 = $10)"
          },
          "total_earned_microcents": {
            "type": "integer",
            "title": "Total Earned Microcents"
          },
          "pending_payout_microcents": {
            "type": "integer",
            "title": "Pending Payout Microcents"
          },
          "total_paid_microcents": {
            "type": "integer",
            "title": "Total Paid Microcents"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "title": "Joined At"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "referral_code",
          "referral_link",
          "status",
          "commission_rate",
          "max_commission_microcents",
          "total_earned_microcents",
          "pending_payout_microcents",
          "total_paid_microcents",
          "joined_at"
        ],
        "title": "AffiliateProfileResponse",
        "description": "Response for GET /affiliates/me — affiliate profile with referral link."
      },
      "AffiliateStatsResponse": {
        "properties": {
          "clicks_30d": {
            "type": "integer",
            "title": "Clicks 30D",
            "description": "Unique clicks in the last 30 days"
          },
          "clicks_90d": {
            "type": "integer",
            "title": "Clicks 90D",
            "description": "Unique clicks in the last 90 days"
          },
          "conversions_total": {
            "type": "integer",
            "title": "Conversions Total",
            "description": "Total conversions (all time)"
          },
          "conversions_pending": {
            "type": "integer",
            "title": "Conversions Pending",
            "description": "Conversions with status=pending"
          },
          "conversions_approved": {
            "type": "integer",
            "title": "Conversions Approved",
            "description": "Conversions with status=approved"
          },
          "conversions_paid": {
            "type": "integer",
            "title": "Conversions Paid",
            "description": "Conversions with status=paid"
          },
          "total_earned_microcents": {
            "type": "integer",
            "title": "Total Earned Microcents",
            "description": "Lifetime earnings in microcents"
          },
          "pending_payout_microcents": {
            "type": "integer",
            "title": "Pending Payout Microcents",
            "description": "Pending payout in microcents"
          }
        },
        "type": "object",
        "required": [
          "clicks_30d",
          "clicks_90d",
          "conversions_total",
          "conversions_pending",
          "conversions_approved",
          "conversions_paid",
          "total_earned_microcents",
          "pending_payout_microcents"
        ],
        "title": "AffiliateStatsResponse",
        "description": "Response for GET /affiliates/me/stats — click and conversion metrics."
      },
      "AgentConfirmRequest": {
        "properties": {
          "setup_intent_id": {
            "type": "string",
            "title": "Setup Intent Id",
            "description": "The Stripe SetupIntent ID returned by /setup-intent."
          }
        },
        "type": "object",
        "required": [
          "setup_intent_id"
        ],
        "title": "AgentConfirmRequest",
        "description": "Request body for POST /agent-onboarding/confirm."
      },
      "AgentConfirmResponse": {
        "properties": {
          "api_key": {
            "type": "string",
            "title": "Api Key",
            "description": "Plaintext API key. Shown only once — store it securely."
          },
          "key_prefix": {
            "type": "string",
            "title": "Key Prefix",
            "description": "Non-secret key prefix for identification."
          },
          "organization_id": {
            "type": "string",
            "title": "Organization Id",
            "description": "ID of the auto-provisioned organization."
          },
          "user_id": {
            "type": "string",
            "title": "User Id",
            "description": "ID of the auto-provisioned user."
          },
          "budget_limit_usd": {
            "type": "number",
            "title": "Budget Limit Usd",
            "description": "Default daily spend cap applied to this key."
          }
        },
        "type": "object",
        "required": [
          "api_key",
          "key_prefix",
          "organization_id",
          "user_id",
          "budget_limit_usd"
        ],
        "title": "AgentConfirmResponse",
        "description": "Response for POST /agent-onboarding/confirm.\n\nThe plaintext API key is returned exactly once — it cannot be retrieved again."
      },
      "AgentFeedbackReportRequest": {
        "properties": {
          "what_tried": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "What Tried",
            "description": "What the agent attempted (e.g. parameters, tier, retries)."
          },
          "what_failed": {
            "type": "string",
            "maxLength": 1000,
            "minLength": 1,
            "title": "What Failed",
            "description": "What went wrong — the core signal used to cluster reports."
          },
          "what_expected": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "What Expected",
            "description": "What the agent expected to happen instead."
          }
        },
        "type": "object",
        "required": [
          "what_failed"
        ],
        "title": "AgentFeedbackReportRequest",
        "description": "Request body for POST /api/v1/agent/feedback.\n\nNo authentication required. Rate limited by client IP.",
        "example": {
          "what_expected": "Rendered HTML content matching what a browser would show",
          "what_failed": "Response consistently returns an empty body with 200 status",
          "what_tried": "Requested mode=auto on a JS-heavy product page, retried 3 times"
        }
      },
      "AgentFeedbackReportResponse": {
        "properties": {
          "report_id": {
            "type": "string",
            "title": "Report Id",
            "description": "Opaque identifier for this report."
          },
          "cluster_key": {
            "type": "string",
            "title": "Cluster Key",
            "description": "Cluster identifier this report was grouped into. Use with the vote endpoint."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Always 'received' on successful submission.",
            "default": "received"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable confirmation.",
            "default": "Thank you for your feedback."
          }
        },
        "type": "object",
        "required": [
          "report_id",
          "cluster_key"
        ],
        "title": "AgentFeedbackReportResponse",
        "description": "Response for a successfully submitted report."
      },
      "AgentFeedbackStatusResponse": {
        "properties": {
          "report_id": {
            "type": "string",
            "title": "Report Id"
          },
          "cluster_key": {
            "type": "string",
            "title": "Cluster Key"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Aggregation-safe status, e.g. 'received', 'investigating', 'fix shipped in vX.Y'."
          },
          "report_count": {
            "type": "integer",
            "title": "Report Count",
            "description": "How many total reports share this cluster (may be < 3; individual reports are always visible to their own submitter via this endpoint)."
          }
        },
        "type": "object",
        "required": [
          "report_id",
          "cluster_key",
          "status",
          "report_count"
        ],
        "title": "AgentFeedbackStatusResponse",
        "description": "Response for GET /api/v1/agent/feedback/{report_id}.\n\nStatus-only lookup — never echoes back the submitted text (defense in\ndepth against PII round-tripping through a public GET)."
      },
      "AgentFeedbackVoteResponse": {
        "properties": {
          "cluster_key": {
            "type": "string",
            "title": "Cluster Key"
          },
          "vote_count": {
            "type": "integer",
            "title": "Vote Count"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "'recorded' if this was a new vote, 'already_voted' if this voter had already confirmed."
          }
        },
        "type": "object",
        "required": [
          "cluster_key",
          "vote_count",
          "status"
        ],
        "title": "AgentFeedbackVoteResponse",
        "description": "Response for POST /api/v1/agent/issues/{cluster_key}/vote."
      },
      "AgentIssueSummary": {
        "properties": {
          "cluster_key": {
            "type": "string",
            "title": "Cluster Key"
          },
          "what_failed_summary": {
            "type": "string",
            "title": "What Failed Summary",
            "description": "Scrubbed, representative summary of what agents reported failing."
          },
          "report_count": {
            "type": "integer",
            "minimum": 3.0,
            "title": "Report Count"
          },
          "vote_count": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Vote Count",
            "description": "Number of 'I hit this too' confirmations."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Derived from the linked GitHub issue's live state (open/closed/labels), or 'investigating' if not yet linked to an issue."
          },
          "linked_github_issue": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Linked Github Issue",
            "description": "GitHub issue number tracking this cluster, if linked."
          },
          "first_seen": {
            "type": "string",
            "format": "date-time",
            "title": "First Seen"
          },
          "last_seen": {
            "type": "string",
            "format": "date-time",
            "title": "Last Seen"
          }
        },
        "type": "object",
        "required": [
          "cluster_key",
          "what_failed_summary",
          "report_count",
          "vote_count",
          "status",
          "first_seen",
          "last_seen"
        ],
        "title": "AgentIssueSummary",
        "description": "A single aggregated, publicly-safe issue cluster.\n\nOnly returned when report_count >= 3 (aggregation minimum threshold\nenforced at the SQL query layer — see routers/agent_feedback.py)."
      },
      "AgentIssuesListResponse": {
        "properties": {
          "issues": {
            "items": {
              "$ref": "#/components/schemas/AgentIssueSummary"
            },
            "type": "array",
            "title": "Issues"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "issues",
          "total"
        ],
        "title": "AgentIssuesListResponse",
        "description": "Response for GET /api/v1/agent/issues."
      },
      "AgentSetupIntentRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email",
            "description": "Email to associate with the pending account."
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "AgentSetupIntentRequest",
        "description": "Request body for POST /agent-onboarding/setup-intent."
      },
      "AgentSetupIntentResponse": {
        "properties": {
          "client_secret": {
            "type": "string",
            "title": "Client Secret",
            "description": "Stripe SetupIntent client secret for Stripe.js."
          },
          "setup_intent_id": {
            "type": "string",
            "title": "Setup Intent Id",
            "description": "Stripe SetupIntent ID to pass to /confirm."
          }
        },
        "type": "object",
        "required": [
          "client_secret",
          "setup_intent_id"
        ],
        "title": "AgentSetupIntentResponse",
        "description": "Response for POST /agent-onboarding/setup-intent."
      },
      "AgentTrialResponse": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          },
          "key_prefix": {
            "type": "string",
            "title": "Key Prefix"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Scopes"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At"
          },
          "request_cap": {
            "type": "integer",
            "title": "Request Cap"
          },
          "docs_url": {
            "type": "string",
            "title": "Docs Url",
            "default": "https://alterlab.io/docs/agent-trial"
          }
        },
        "type": "object",
        "required": [
          "key",
          "key_prefix",
          "scopes",
          "expires_at",
          "request_cap"
        ],
        "title": "AgentTrialResponse",
        "description": "Response for a freshly issued agent trial token.\n\n``key`` is shown exactly once, at creation — it is stored hashed\n(Argon2) like every other API key and cannot be retrieved again."
      },
      "AlertHistoryListResponse": {
        "properties": {
          "alerts": {
            "items": {
              "$ref": "#/components/schemas/AlertHistoryResponse"
            },
            "type": "array",
            "title": "Alerts"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "alerts",
          "total"
        ],
        "title": "AlertHistoryListResponse",
        "description": "List of alert history entries."
      },
      "AlertHistoryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "alert_rule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Alert Rule Id"
          },
          "alert_type": {
            "type": "string",
            "title": "Alert Type"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "details": {
            "additionalProperties": true,
            "type": "object",
            "title": "Details"
          },
          "delivered_via": {
            "additionalProperties": true,
            "type": "object",
            "title": "Delivered Via"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "alert_rule_id",
          "alert_type",
          "message",
          "details",
          "delivered_via",
          "created_at"
        ],
        "title": "AlertHistoryResponse",
        "description": "Single alert history entry."
      },
      "AlertRuleCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "Human-readable name"
          },
          "alert_type": {
            "$ref": "#/components/schemas/AlertType",
            "description": "Type of alert to create"
          },
          "conditions": {
            "additionalProperties": true,
            "type": "object",
            "title": "Conditions",
            "description": "Conditions for the alert (varies by alert_type)"
          },
          "domain_filter": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain Filter",
            "description": "Optional list of domains to scope this alert to"
          },
          "channels": {
            "additionalProperties": true,
            "type": "object",
            "title": "Channels",
            "description": "Delivery channels: {email: bool, webhook_id: str}",
            "default": {
              "email": true
            }
          },
          "cooldown_minutes": {
            "type": "integer",
            "maximum": 1440.0,
            "minimum": 5.0,
            "title": "Cooldown Minutes",
            "description": "Minutes to wait before re-alerting (5 min to 24 hours)",
            "default": 60
          }
        },
        "type": "object",
        "required": [
          "name",
          "alert_type",
          "conditions"
        ],
        "title": "AlertRuleCreate",
        "description": "Create a new alert rule."
      },
      "AlertRuleListResponse": {
        "properties": {
          "rules": {
            "items": {
              "$ref": "#/components/schemas/AlertRuleResponse"
            },
            "type": "array",
            "title": "Rules"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "rules",
          "total"
        ],
        "title": "AlertRuleListResponse",
        "description": "List of alert rules."
      },
      "AlertRuleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "alert_type": {
            "type": "string",
            "title": "Alert Type"
          },
          "conditions": {
            "additionalProperties": true,
            "type": "object",
            "title": "Conditions"
          },
          "domain_filter": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain Filter"
          },
          "channels": {
            "additionalProperties": true,
            "type": "object",
            "title": "Channels"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "last_triggered_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Triggered At"
          },
          "cooldown_minutes": {
            "type": "integer",
            "title": "Cooldown Minutes"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "organization_id",
          "name",
          "alert_type",
          "conditions",
          "channels",
          "is_active",
          "cooldown_minutes",
          "created_at",
          "updated_at"
        ],
        "title": "AlertRuleResponse",
        "description": "Alert rule detail."
      },
      "AlertRuleUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "conditions": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Conditions"
          },
          "domain_filter": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain Filter"
          },
          "channels": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Channels"
          },
          "cooldown_minutes": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 1440.0,
                "minimum": 5.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Cooldown Minutes"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          }
        },
        "type": "object",
        "title": "AlertRuleUpdate",
        "description": "Update an existing alert rule."
      },
      "AlertType": {
        "type": "string",
        "enum": [
          "credit_threshold",
          "domain_failure_rate",
          "job_consecutive_failures",
          "response_time_spike",
          "daily_failure_count",
          "schedule_failure"
        ],
        "title": "AlertType",
        "description": "Supported alert types."
      },
      "AllKeysUsageResponse": {
        "properties": {
          "keys": {
            "items": {
              "$ref": "#/components/schemas/KeyUsageSummary"
            },
            "type": "array",
            "title": "Keys"
          },
          "account_total_spend_microcents": {
            "type": "integer",
            "title": "Account Total Spend Microcents",
            "default": 0
          },
          "account_total_requests": {
            "type": "integer",
            "title": "Account Total Requests",
            "default": 0
          },
          "period_start": {
            "type": "string",
            "format": "date-time",
            "title": "Period Start"
          },
          "period_end": {
            "type": "string",
            "format": "date-time",
            "title": "Period End"
          }
        },
        "type": "object",
        "required": [
          "keys",
          "period_start",
          "period_end"
        ],
        "title": "AllKeysUsageResponse",
        "description": "Response for /usage/by-key endpoint."
      },
      "AttachmentRef": {
        "properties": {
          "storage_key": {
            "type": "string",
            "maxLength": 1000,
            "title": "Storage Key"
          },
          "filename": {
            "type": "string",
            "maxLength": 500,
            "title": "Filename"
          },
          "content_type": {
            "type": "string",
            "maxLength": 200,
            "title": "Content Type"
          },
          "size_bytes": {
            "type": "integer",
            "exclusiveMinimum": 0.0,
            "title": "Size Bytes"
          }
        },
        "type": "object",
        "required": [
          "storage_key",
          "filename",
          "content_type",
          "size_bytes"
        ],
        "title": "AttachmentRef",
        "description": "Lightweight reference to an attachment included in a create request.\n\nClients upload files first (to /support/attachments) and then pass the\nreturned storage keys here so the ticket / reply creation endpoint can\nlink them."
      },
      "AttachmentResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "filename": {
            "type": "string",
            "title": "Filename"
          },
          "content_type": {
            "type": "string",
            "title": "Content Type"
          },
          "size_bytes": {
            "type": "integer",
            "title": "Size Bytes"
          },
          "storage_key": {
            "type": "string",
            "title": "Storage Key"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "filename",
          "content_type",
          "size_bytes",
          "storage_key",
          "created_at"
        ],
        "title": "AttachmentResponse",
        "description": "Attachment metadata returned as part of a reply."
      },
      "AttributionData": {
        "properties": {
          "utm_source": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Source",
            "description": "UTM source parameter"
          },
          "utm_medium": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Medium",
            "description": "UTM medium parameter"
          },
          "utm_campaign": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Campaign",
            "description": "UTM campaign parameter"
          },
          "utm_content": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Content",
            "description": "UTM content parameter"
          },
          "utm_term": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Utm Term",
            "description": "UTM term parameter"
          },
          "referrer_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Referrer Url",
            "description": "HTTP referrer at first visit"
          },
          "referrer_domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Referrer Domain",
            "description": "Hostname extracted from referrer_url (e.g. 'reddit.com')"
          },
          "landing_page": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Landing Page",
            "description": "First page the user landed on"
          },
          "signup_method": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Signup Method",
            "description": "How the user signed up (e.g., header_cta, pricing_page)"
          },
          "affiliate_ref": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Affiliate Ref",
            "description": "Affiliate referral code from ref= URL parameter"
          }
        },
        "type": "object",
        "title": "AttributionData",
        "description": "First-touch attribution data captured at signup.\n\nAll fields are optional strings — the frontend sends whatever it has.\nValues are sanitized (HTML stripped, max 500 chars each)."
      },
      "AuditLogActor": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email"
        ],
        "title": "AuditLogActor",
        "description": "Actor information for audit log."
      },
      "AuditLogListResponse": {
        "properties": {
          "logs": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__organization__AuditLogEntry"
            },
            "type": "array",
            "title": "Logs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "offset": {
            "type": "integer",
            "title": "Offset"
          }
        },
        "type": "object",
        "required": [
          "logs",
          "total",
          "limit",
          "offset"
        ],
        "title": "AuditLogListResponse",
        "description": "Paginated audit log list response."
      },
      "AuditLogResponse": {
        "properties": {
          "entries": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__billing__AuditLogEntry"
            },
            "type": "array",
            "title": "Entries"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More"
          }
        },
        "type": "object",
        "required": [
          "entries",
          "total",
          "has_more"
        ],
        "title": "AuditLogResponse",
        "description": "Audit log response."
      },
      "AuthResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "email_verified": {
            "type": "boolean",
            "title": "Email Verified"
          },
          "is_admin": {
            "type": "boolean",
            "title": "Is Admin",
            "default": false
          },
          "session_token": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Token"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email",
          "name",
          "email_verified"
        ],
        "title": "AuthResponse"
      },
      "AuthorizeRequest": {
        "properties": {
          "client_id": {
            "type": "string",
            "title": "Client Id"
          },
          "redirect_uri": {
            "type": "string",
            "title": "Redirect Uri"
          },
          "state": {
            "type": "string",
            "title": "State"
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "default": "scrape"
          },
          "source": {
            "type": "string",
            "title": "Source",
            "default": "unknown"
          }
        },
        "type": "object",
        "required": [
          "client_id",
          "redirect_uri",
          "state"
        ],
        "title": "AuthorizeRequest",
        "description": "Request to generate an OAuth2 authorization code."
      },
      "AuthorizeResponse": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          },
          "state": {
            "type": "string",
            "title": "State"
          }
        },
        "type": "object",
        "required": [
          "code",
          "state"
        ],
        "title": "AuthorizeResponse",
        "description": "Response with the authorization code."
      },
      "AutoRechargeSettingsRequest": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Enable auto-recharge",
            "default": false
          },
          "threshold_microcents": {
            "type": "integer",
            "maximum": 50000000000.0,
            "minimum": 1000000.0,
            "title": "Threshold Microcents",
            "description": "Recharge when balance drops below this (microcents). 1,000,000 = $1.00",
            "default": 5000000
          },
          "recharge_amount_cents": {
            "type": "integer",
            "maximum": 200000.0,
            "minimum": 2500.0,
            "title": "Recharge Amount Cents",
            "description": "Amount to charge in cents ($25-$2000)",
            "default": 5000
          },
          "stripe_payment_method_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Payment Method Id",
            "description": "Stripe payment method ID for off-session charges"
          },
          "consent_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Consent Text",
            "description": "Snapshot of the consent copy shown to user"
          },
          "consent_source": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "deposit_flow",
                  "success_page",
                  "settings"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Consent Source",
            "description": "Where the user opted in"
          },
          "terms_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Terms Version",
            "description": "ToS version at consent time"
          }
        },
        "type": "object",
        "title": "AutoRechargeSettingsRequest",
        "description": "Request to create or update auto-recharge settings."
      },
      "AutoRechargeSettingsResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "threshold_microcents": {
            "type": "integer",
            "title": "Threshold Microcents"
          },
          "threshold_display": {
            "type": "string",
            "title": "Threshold Display",
            "default": ""
          },
          "recharge_amount_cents": {
            "type": "integer",
            "title": "Recharge Amount Cents"
          },
          "recharge_amount_display": {
            "type": "string",
            "title": "Recharge Amount Display",
            "default": ""
          },
          "stripe_payment_method_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Payment Method Id"
          },
          "consent_accepted_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Consent Accepted At"
          },
          "consent_source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Consent Source"
          },
          "terms_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Terms Version"
          },
          "last_recharge_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Recharge At"
          },
          "last_failure_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Failure At"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count",
            "default": 0
          },
          "paused_until": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paused Until"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "enabled",
          "threshold_microcents",
          "recharge_amount_cents",
          "created_at",
          "updated_at"
        ],
        "title": "AutoRechargeSettingsResponse",
        "description": "Auto-recharge settings for a user."
      },
      "AutoRechargeSummary": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": false
          },
          "threshold_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Threshold Display"
          },
          "recharge_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recharge Display"
          }
        },
        "type": "object",
        "title": "AutoRechargeSummary",
        "description": "Auto-recharge configuration summary."
      },
      "AutoRechargeTestResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "payment_method_valid": {
            "type": "boolean",
            "title": "Payment Method Valid",
            "default": false
          },
          "card_expired": {
            "type": "boolean",
            "title": "Card Expired",
            "default": false
          },
          "card_days_until_expiry": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Days Until Expiry"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "card_brand": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Brand"
          },
          "card_last4": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Last4"
          }
        },
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "title": "AutoRechargeTestResponse",
        "description": "Result of a dry-run auto-recharge validation.\n\nTests that the saved payment method is valid and that fraud checks\npass — without actually creating a charge."
      },
      "B2BBillingSummaryResponse": {
        "properties": {
          "period_start": {
            "type": "string",
            "format": "date-time",
            "title": "Period Start",
            "description": "Period start (inclusive, UTC)."
          },
          "period_end": {
            "type": "string",
            "format": "date-time",
            "title": "Period End",
            "description": "Period end (inclusive, UTC)."
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests",
            "description": "Total scrape requests in period"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests",
            "description": "Successful requests in period"
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests",
            "description": "Failed requests in period"
          },
          "total_cost_microcents": {
            "type": "integer",
            "title": "Total Cost Microcents",
            "description": "Total charges at your negotiated rate for this period. 1,000,000 microcents = $1.00."
          },
          "billing_model": {
            "type": "string",
            "title": "Billing Model",
            "description": "Billing model: 'prepaid' (balance-based) or 'invoice' (net-30)."
          },
          "contracted_monthly_fee_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Contracted Monthly Fee Usd",
            "description": "Contracted monthly fee in USD, if specified in your contract. Null if not parseable from contract notes."
          },
          "tier_breakdown": {
            "items": {
              "$ref": "#/components/schemas/B2BBillingSummaryTierBreakdown"
            },
            "type": "array",
            "title": "Tier Breakdown",
            "description": "Per-tier cost breakdown for the period."
          }
        },
        "type": "object",
        "required": [
          "period_start",
          "period_end",
          "total_requests",
          "successful_requests",
          "failed_requests",
          "total_cost_microcents",
          "billing_model"
        ],
        "title": "B2BBillingSummaryResponse",
        "description": "Client-facing billing summary for a B2B enterprise tenant.\n\nReturned by GET /billing/b2b/summary. Scoped to the calling organization.\nExcludes internal cost data (proxy COGS, margin, global-rate comparison).\nOnly available for organizations with a tenant_billing_config row."
      },
      "B2BBillingSummaryTierBreakdown": {
        "properties": {
          "tier": {
            "type": "string",
            "title": "Tier",
            "description": "Scraping tier identifier (e.g. '1', '2', '3', '3.5', '4', '5')"
          },
          "request_count": {
            "type": "integer",
            "title": "Request Count",
            "description": "Total requests in this tier for the period"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests",
            "description": "Successful requests in this tier"
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests",
            "description": "Failed requests in this tier"
          },
          "cost_at_contracted_rate_microcents": {
            "type": "integer",
            "title": "Cost At Contracted Rate Microcents",
            "description": "Charges at your contracted rate for this tier. Sourced from jobs.credits_used, which is set at debit time using your negotiated tier_overrides (from tenant_billing_config). This is NOT the standard list price — it reflects the rate agreed in your contract. 1,000,000 microcents = $1.00."
          }
        },
        "type": "object",
        "required": [
          "tier",
          "request_count",
          "successful_requests",
          "failed_requests",
          "cost_at_contracted_rate_microcents"
        ],
        "title": "B2BBillingSummaryTierBreakdown",
        "description": "Per-tier aggregation for client-facing B2B billing summary.\n\nClient-safe subset of TenantTierBreakdown — excludes internal cost data\n(proxy COGS, global-rate comparison, discount delta)."
      },
      "B2BHealthResponse": {
        "properties": {
          "window": {
            "type": "string",
            "enum": [
              "24h",
              "7d",
              "30d"
            ],
            "title": "Window",
            "description": "Aggregation window: '24h' (last 24 hours), '7d' (last 7 days), '30d' (last 30 days)."
          },
          "ad_fill_rate": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Fill Rate",
            "description": "Fraction of SERP jobs that returned at least one ad in the window (0.0–1.0).  None when no data is available."
          },
          "ad_fill_rate_jobs": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Fill Rate Jobs",
            "description": "Total SERP jobs included in the ad_fill_rate calculation.  None when ad_fill_rate is None."
          },
          "serp_success_rate": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Serp Success Rate",
            "description": "Fraction of SERP jobs that returned at least one organic result (status='succeeded') in the window.  None when no data is available."
          },
          "serp_success_rate_jobs": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Serp Success Rate Jobs",
            "description": "Total SERP jobs included in the serp_success_rate calculation.  None when serp_success_rate is None."
          },
          "delivery_success_rate": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Delivery Success Rate",
            "description": "Fraction of delivery attempts that succeeded in the window (0.0–1.0).  None when no delivery attempts have been made or DB is unavailable."
          },
          "deliveries_total": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Deliveries Total",
            "description": "Total delivery attempts in the window.  None when delivery_success_rate is None."
          },
          "deliveries_succeeded": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Deliveries Succeeded",
            "description": "Successful delivery attempts in the window.  None when delivery_success_rate is None."
          },
          "batches_submitted": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Batches Submitted",
            "description": "Total bulk submissions accepted in the window.  None when DB is unavailable."
          },
          "batches_completed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Batches Completed",
            "description": "Bulk submissions that reached status='completed' in the window.  None when DB is unavailable."
          },
          "system_status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ],
            "title": "System Status",
            "description": "'ok' — Redis is reachable.  'degraded' — Redis ping failed; scraping pipeline may be impaired."
          },
          "sla_thresholds": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/B2BSLAThresholds"
              },
              {
                "type": "null"
              }
            ],
            "description": "SLA thresholds configured for this tenant in tenant_config.sla.  None when not configured."
          },
          "data_available": {
            "type": "boolean",
            "title": "Data Available",
            "description": "False when at least one metric could not be fetched (e.g., Redis unavailable, table empty).  True when all metrics were successfully retrieved."
          }
        },
        "type": "object",
        "required": [
          "window",
          "system_status",
          "data_available"
        ],
        "title": "B2BHealthResponse",
        "description": "Response body for GET /api/v1/b2b/health.\n\nAll rate fields are expressed as fractions (0.0–1.0), not percentages.\nFields are ``None`` when the underlying data source is unavailable\n(Redis down, table not yet populated, etc.).  ``data_available`` is\n``False`` when at least one metric could not be retrieved."
      },
      "B2BSLAThresholds": {
        "properties": {
          "ad_fill_rate_min": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Fill Rate Min",
            "description": "Minimum acceptable ad fill rate (0.0–1.0). None when not configured."
          },
          "serp_success_rate_min": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Serp Success Rate Min",
            "description": "Minimum acceptable SERP success rate (0.0–1.0). None when not configured."
          },
          "delivery_success_rate_min": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Delivery Success Rate Min",
            "description": "Minimum acceptable delivery success rate (0.0–1.0). None when not configured."
          }
        },
        "type": "object",
        "title": "B2BSLAThresholds",
        "description": "SLA thresholds configured for this tenant.\n\nRead from ``org.tenant_config['sla']`` if present; ``None`` otherwise.\nReturned as-is so the client can compare observed metrics against their\ncontracted thresholds."
      },
      "B2BUsageBillingPeriod": {
        "properties": {
          "start": {
            "type": "string",
            "title": "Start",
            "description": "Billing period start date (ISO 8601, YYYY-MM-DD)."
          },
          "end": {
            "type": "string",
            "title": "End",
            "description": "Billing period end date (ISO 8601, YYYY-MM-DD)."
          }
        },
        "type": "object",
        "required": [
          "start",
          "end"
        ],
        "title": "B2BUsageBillingPeriod",
        "description": "Current billing period boundaries for the calling organization.\n\nSourced from ``get_organization_billing_stats()``\n(``app.billing.metering``) — the same period-resolution logic used by\nthe internal billing stats endpoint. ISO 8601 date strings (``YYYY-MM-DD``)."
      },
      "B2BUsageResponse": {
        "properties": {
          "billing_period": {
            "$ref": "#/components/schemas/B2BUsageBillingPeriod",
            "description": "Current billing period start/end for the calling org."
          },
          "queries_used": {
            "type": "integer",
            "title": "Queries Used",
            "description": "Count of UsageTracking rows for this org in the current billing period (organization_id + created_at in [period_start, period_end))."
          },
          "queries_limit": {
            "type": "integer",
            "title": "Queries Limit",
            "description": "Contracted query quota for this org. Read from org.tenant_config['queries_limit'] JSONB field; falls back to the documented plan default when not configured."
          },
          "ad_fill_rate": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Ad Fill Rate",
            "description": "Fraction of SERP jobs that returned at least one ad in the billing period (0.0-1.0). None when no data is available."
          },
          "avg_ads_per_query": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Ads Per Query",
            "description": "Average number of ads returned per SERP query in the billing period (total_ads / total). None when the total_ads Redis field is unavailable or zero (e.g. pre-#28181 data)."
          },
          "demographic_ad_rate": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Demographic Ad Rate",
            "description": "Fraction of served ads that were demographically targeted (demographic_ads / total_ads). None when the demographic_ads Redis field is unavailable or total_ads is zero."
          },
          "bulk_jobs_submitted": {
            "type": "integer",
            "title": "Bulk Jobs Submitted",
            "description": "Total bulk submissions accepted by this org in the billing period."
          },
          "bulk_jobs_completed": {
            "type": "integer",
            "title": "Bulk Jobs Completed",
            "description": "Bulk submissions that reached status='completed' in the billing period."
          },
          "bulk_jobs_failed": {
            "type": "integer",
            "title": "Bulk Jobs Failed",
            "description": "Bulk submissions that reached status='failed' in the billing period."
          }
        },
        "type": "object",
        "required": [
          "billing_period",
          "queries_used",
          "queries_limit",
          "bulk_jobs_submitted",
          "bulk_jobs_completed",
          "bulk_jobs_failed"
        ],
        "title": "B2BUsageResponse",
        "description": "Response body for GET /api/v1/b2b/usage.\n\nScoped to the authenticated enterprise org — no cross-tenant data.\nAd/demographic metric fields are ``None`` when the underlying Redis\n``serp:ad_metrics`` fields are unavailable or not yet populated (e.g.\n``total_ads``/``demographic_ads`` are absent prior to #28181 rollout for\na given tenant). ``queries_used``, ``queries_limit``, ``billing_period``,\nand the bulk-job counters are always populated from the database and are\nnon-Optional."
      },
      "BalanceResponse": {
        "properties": {
          "balance_microcents": {
            "type": "integer",
            "title": "Balance Microcents"
          },
          "balance_display": {
            "type": "string",
            "title": "Balance Display"
          },
          "total_deposited_cents": {
            "type": "integer",
            "title": "Total Deposited Cents"
          },
          "total_spent_cents": {
            "type": "integer",
            "title": "Total Spent Cents"
          },
          "total_granted_cents": {
            "type": "integer",
            "title": "Total Granted Cents",
            "default": 0
          },
          "tier": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/app__schemas__billing__TierInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "auto_recharge": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AutoRechargeSummary"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "balance_microcents",
          "balance_display",
          "total_deposited_cents",
          "total_spent_cents"
        ],
        "title": "BalanceResponse",
        "description": "User balance response.\n\nNote: balance_microcents uses microcents for sub-cent precision.\n1,000,000 microcents = $1.00"
      },
      "BatchAnalyticsResponse": {
        "properties": {
          "summary": {
            "$ref": "#/components/schemas/BatchAnalyticsSummary"
          },
          "daily_stats": {
            "items": {
              "$ref": "#/components/schemas/BatchDailyStat"
            },
            "type": "array",
            "title": "Daily Stats"
          },
          "domain_breakdown": {
            "items": {
              "$ref": "#/components/schemas/BatchDomainBreakdown"
            },
            "type": "array",
            "title": "Domain Breakdown"
          },
          "tier_distribution": {
            "$ref": "#/components/schemas/BatchTierDistribution"
          }
        },
        "type": "object",
        "required": [
          "summary",
          "daily_stats",
          "domain_breakdown",
          "tier_distribution"
        ],
        "title": "BatchAnalyticsResponse",
        "description": "Response from the batch analytics endpoint."
      },
      "BatchAnalyticsSummary": {
        "properties": {
          "total_batches": {
            "type": "integer",
            "title": "Total Batches",
            "default": 0
          },
          "total_urls": {
            "type": "integer",
            "title": "Total Urls",
            "default": 0
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "default": 0.0
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits",
            "default": 0
          }
        },
        "type": "object",
        "title": "BatchAnalyticsSummary",
        "description": "Summary statistics for batch analytics."
      },
      "BatchDailyStat": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "batches": {
            "type": "integer",
            "title": "Batches",
            "default": 0
          },
          "urls": {
            "type": "integer",
            "title": "Urls",
            "default": 0
          },
          "succeeded": {
            "type": "integer",
            "title": "Succeeded",
            "default": 0
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "default": 0
          },
          "credits": {
            "type": "integer",
            "title": "Credits",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "date"
        ],
        "title": "BatchDailyStat",
        "description": "Daily aggregated batch statistics."
      },
      "BatchDomainBreakdown": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "url_count": {
            "type": "integer",
            "title": "Url Count",
            "default": 0
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "default": 0.0
          },
          "avg_credits": {
            "type": "number",
            "title": "Avg Credits",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "domain"
        ],
        "title": "BatchDomainBreakdown",
        "description": "Per-domain batch statistics."
      },
      "BatchExportConfig": {
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "title": "Integration Id",
            "description": "Storage integration ID to export to"
          },
          "prefix": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Prefix",
            "description": "Key prefix override (uses integration default if not set)"
          },
          "format": {
            "type": "string",
            "enum": [
              "jsonl",
              "csv",
              "json"
            ],
            "title": "Format",
            "description": "Export file format",
            "default": "jsonl"
          }
        },
        "type": "object",
        "required": [
          "integration_id"
        ],
        "title": "BatchExportConfig",
        "description": "Export configuration for batch results to cloud storage."
      },
      "BatchItemRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto",
              "html",
              "js",
              "pdf",
              "ocr"
            ],
            "title": "Mode",
            "description": "Scraping mode",
            "default": "auto"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ],
            "title": "Method",
            "description": "HTTP method for this URL. Default GET. Use POST for GraphQL endpoints, REST APIs, and form submissions. POST costs 1.5x the base tier price.",
            "default": "GET"
          },
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Body",
            "description": "Request body for POST. Must be a UTF-8 string. Maximum 1 MB (10 MB for high-volume/enterprise tiers). For JSON payloads (GraphQL, REST) set content_type='application/json'. Cannot be used with method='GET'. PRIVACY: Body content is never logged or stored in job records."
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "application/json",
                  "application/x-www-form-urlencoded",
                  "text/plain",
                  "application/graphql"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Type",
            "description": "Content-Type header for the request body. Defaults to 'application/json' when body is provided. Ignored when body is not set."
          },
          "advanced": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AdvancedOptions"
              },
              {
                "type": "null"
              }
            ]
          },
          "location": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Location"
              },
              {
                "type": "null"
              }
            ],
            "description": "Geo-targeting parameters for this URL."
          },
          "cost_controls": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CostControls"
              },
              {
                "type": "null"
              }
            ]
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown",
                    "rag",
                    "content",
                    "raw"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema"
          },
          "extraction_prompt": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Prompt",
            "description": "Natural language extraction instruction for this URL"
          },
          "extraction_provider": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "openai",
                  "anthropic",
                  "openrouter",
                  "groq"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Provider",
            "description": "Not supported for batch requests. Set extraction_provider at the batch level (BatchRequest.extraction_provider) instead — BYOK key resolution happens once before the bulk pre-debit and applies to all items. Per-item provider overrides are rejected with HTTP 422."
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Pre-defined extraction profile",
            "default": "auto"
          },
          "extraction_template": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Template",
            "description": "Shorthand for extraction_profile. Selects a pre-built schema template by name. Mutually exclusive with extraction_profile."
          },
          "cache": {
            "type": "boolean",
            "title": "Cache",
            "description": "Enable caching for this URL",
            "default": false
          },
          "include_raw_html": {
            "type": "boolean",
            "title": "Include Raw Html",
            "default": false
          },
          "timeout": {
            "type": "integer",
            "maximum": 300.0,
            "minimum": 1.0,
            "title": "Timeout",
            "default": 90
          },
          "wait_for": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wait For"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "BatchItemRequest",
        "description": "Single item in a batch scrape request."
      },
      "BatchItemStatus": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "url",
          "status"
        ],
        "title": "BatchItemStatus",
        "description": "Status of a single item within a batch."
      },
      "BatchListItem": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id"
          },
          "url_count": {
            "type": "integer",
            "title": "Url Count"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "default": 0
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "default": 0
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "default": 0
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "url_count",
          "status",
          "created_at"
        ],
        "title": "BatchListItem",
        "description": "Summary of a single batch in the user's batch history."
      },
      "BatchListResponse": {
        "properties": {
          "batches": {
            "items": {
              "$ref": "#/components/schemas/BatchListItem"
            },
            "type": "array",
            "title": "Batches"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "batches",
          "total"
        ],
        "title": "BatchListResponse",
        "description": "Response from listing user's batch history."
      },
      "BatchRequest": {
        "properties": {
          "urls": {
            "items": {
              "$ref": "#/components/schemas/BatchItemRequest"
            },
            "type": "array",
            "maxItems": 100,
            "minItems": 1,
            "title": "Urls",
            "description": "List of URLs to scrape (max 100)"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "BYOS session ID to apply to all URLs in the batch. All URLs must match the session's domain."
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL to receive batch.completed event when all jobs finish"
          },
          "export": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BatchExportConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cloud storage export config — results uploaded on batch completion"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON Schema applied to all URLs that do not supply their own extraction_schema. The worker runs LLM-based schema extraction and returns a structured object matching this schema in the job result. Mutually exclusive with extraction_prompt."
          },
          "extraction_prompt": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Prompt",
            "description": "Natural language extraction instruction applied to all URLs that do not supply their own extraction_prompt. Mutually exclusive with extraction_schema."
          },
          "extraction_provider": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "openai",
                  "anthropic",
                  "openrouter",
                  "groq"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Provider",
            "description": "LLM provider to use for extraction. Selects the matching BYOK key registered at /dashboard/settings/llm-keys. When omitted, the most recently used registered key is used automatically."
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Pre-defined extraction profile applied to all URLs that do not supply their own extraction_profile. Overridden by item-level extraction_profile."
          }
        },
        "type": "object",
        "required": [
          "urls"
        ],
        "title": "BatchRequest",
        "description": "Batch scraping request — up to 100 URLs."
      },
      "BatchResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id"
          },
          "total_urls": {
            "type": "integer",
            "title": "Total Urls"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "default": "processing"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits",
            "description": "Total credits pre-debited for this batch"
          },
          "job_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Job Ids",
            "description": "Individual job IDs for each URL"
          },
          "byos_applied": {
            "type": "boolean",
            "title": "Byos Applied",
            "description": "Whether BYOS session cookies were applied to all URLs in this batch",
            "default": false
          },
          "byos_session_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Byos Session Name",
            "description": "Name of the BYOS session used (if any)"
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "total_urls",
          "estimated_credits",
          "job_ids"
        ],
        "title": "BatchResponse",
        "description": "Response returned immediately after submitting a batch."
      },
      "BatchSearchItemStatus": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id",
            "description": "SERP job ID for this query"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Status: queued, processing, succeeded, failed, expired"
          },
          "results_requested": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Results Requested",
            "description": "Number of results requested for this query (the batch num_results parameter). Populated when status=succeeded."
          },
          "results_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Results Count",
            "description": "Number of results actually returned (may be less than results_requested if fewer results were available after deduplication/filtering). Populated when status=succeeded."
          },
          "results": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SearchResult"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Results",
            "description": "Search results (populated when status=succeeded)"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message (populated when status=failed)"
          },
          "credits_used": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Credits Used",
            "description": "Credits debited for this query (base + scrape costs when applicable)"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "query",
          "status"
        ],
        "title": "BatchSearchItemStatus",
        "description": "Status of a single query within a batch search."
      },
      "BatchSearchRequest": {
        "properties": {
          "queries": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 50,
            "minItems": 1,
            "title": "Queries",
            "description": "Search queries to execute (1-50 queries, each max 500 characters)"
          },
          "engine": {
            "type": "string",
            "enum": [
              "duckduckgo",
              "google",
              "bing"
            ],
            "title": "Engine",
            "description": "Search engine to use for all queries in this batch. 'duckduckgo' (default) is fast and cheap ($0.001/query). 'google' and 'bing' use browser-tier rendering ($0.004/query).",
            "default": "duckduckgo"
          },
          "num_results": {
            "type": "integer",
            "maximum": 30.0,
            "minimum": 1.0,
            "title": "Num Results",
            "description": "Number of results per query (1-30)",
            "default": 10
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code applied to all queries (e.g., US, GB, DE)"
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Language code applied to all queries (e.g., en, fr, de)"
          },
          "time_range": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "hour",
                  "day",
                  "week",
                  "month",
                  "year"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Time Range",
            "description": "Filter results by recency (applied to all queries)"
          },
          "safe_search": {
            "type": "boolean",
            "title": "Safe Search",
            "description": "Enable safe search filtering (default: true). When false, disables DDG Lite's adult content filter (sends p=-1 instead of p=-2). Applied to all queries.",
            "default": true
          },
          "scrape_results": {
            "type": "boolean",
            "title": "Scrape Results",
            "description": "If true, scrape each result page for content. Per-page tier costs are debited as scrapes complete.",
            "default": false
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown",
                    "rag",
                    "content"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats when scrape_results=true"
          },
          "tenant_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenant Id",
            "description": "B2B tenant identifier for engine routing (e.g. 'marcode'). Internal use."
          },
          "session_pool_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Pool Id",
            "description": "Explicit session pool identifier for B2B demographic routing (#20410). When set, overrides tenant_id as the pool key passed to SerpSessionPool.acquire_session(), enabling per-profile ad result collection from separate demographic session pools under the same tenant. Falls back to tenant_id when absent. Internal use."
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL to POST when all queries complete. Receives a batch.search.completed event with all results."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "queries"
        ],
        "title": "BatchSearchRequest",
        "description": "Request body for POST /v1/search/batch.\n\nSubmit up to 50 queries for asynchronous parallel SERP processing.\nEach query is billed at the engine-specific rate up front (e.g. 1000mc for\nDuckDuckGo, 4000mc for Google/Bing).\nWhen scrape_results=true, per-page tier costs are debited as results arrive."
      },
      "BatchSearchResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id",
            "description": "Unique identifier for this batch search"
          },
          "total_queries": {
            "type": "integer",
            "title": "Total Queries",
            "description": "Number of queries submitted"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Batch status: processing",
            "default": "processing"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits",
            "description": "Credits pre-debited for this batch (base search cost × queries). Additional credits are debited per page when scrape_results=true."
          },
          "job_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Job Ids",
            "description": "Individual SERP job IDs, one per query"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Batch search submitted. Poll GET /v1/search/batch/{batch_id} for results."
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "total_queries",
          "estimated_credits",
          "job_ids"
        ],
        "title": "BatchSearchResponse",
        "description": "Response from POST /v1/search/batch (202 Accepted)."
      },
      "BatchSearchStatusResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Overall batch status: processing, completed, partial, failed"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of queries in the batch"
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "description": "Number of queries with results"
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "description": "Number of queries that failed"
          },
          "pending": {
            "type": "integer",
            "title": "Pending",
            "description": "Number of queries still in progress"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/BatchSearchItemStatus"
            },
            "type": "array",
            "title": "Items",
            "description": "Per-query status and results"
          },
          "total_credits_used": {
            "type": "integer",
            "title": "Total Credits Used",
            "description": "Total credits debited for this batch so far"
          },
          "created_at": {
            "type": "string",
            "title": "Created At",
            "description": "ISO 8601 timestamp when batch was created"
          },
          "webhook_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Status",
            "description": "Webhook delivery status: pending, delivered, retrying, failed, cancelled"
          },
          "webhook_attempts": {
            "type": "integer",
            "title": "Webhook Attempts",
            "description": "Number of webhook delivery attempts made",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "status",
          "total",
          "completed",
          "failed",
          "pending",
          "items",
          "total_credits_used",
          "created_at"
        ],
        "title": "BatchSearchStatusResponse",
        "description": "Response from GET /v1/search/batch/{batch_id}."
      },
      "BatchStatusResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "completed": {
            "type": "integer",
            "title": "Completed"
          },
          "failed": {
            "type": "integer",
            "title": "Failed"
          },
          "pending": {
            "type": "integer",
            "title": "Pending"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/BatchItemStatus"
            },
            "type": "array",
            "title": "Items"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "export_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Export Status"
          },
          "export_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Export Error"
          },
          "webhook_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Status"
          },
          "webhook_attempts": {
            "type": "integer",
            "title": "Webhook Attempts",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "status",
          "total",
          "completed",
          "failed",
          "pending",
          "items",
          "created_at"
        ],
        "title": "BatchStatusResponse",
        "description": "Response from polling batch status."
      },
      "BatchTierDistribution": {
        "properties": {
          "tier_1": {
            "type": "integer",
            "title": "Tier 1",
            "default": 0
          },
          "tier_2": {
            "type": "integer",
            "title": "Tier 2",
            "default": 0
          },
          "tier_3": {
            "type": "integer",
            "title": "Tier 3",
            "default": 0
          },
          "tier_4": {
            "type": "integer",
            "title": "Tier 4",
            "default": 0
          }
        },
        "type": "object",
        "title": "BatchTierDistribution",
        "description": "Tier usage distribution across batch jobs."
      },
      "BeaconBatch": {
        "properties": {
          "events": {
            "items": {
              "$ref": "#/components/schemas/BeaconEvent"
            },
            "type": "array",
            "maxItems": 50,
            "minItems": 1,
            "title": "Events"
          }
        },
        "type": "object",
        "required": [
          "events"
        ],
        "title": "BeaconBatch",
        "description": "Batch of events from a single sendBeacon call."
      },
      "BeaconEvent": {
        "properties": {
          "event_type": {
            "type": "string",
            "title": "Event Type"
          },
          "properties": {
            "additionalProperties": true,
            "type": "object",
            "title": "Properties"
          },
          "timestamp": {
            "type": "number",
            "title": "Timestamp"
          },
          "anonymous_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Anonymous Id"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          }
        },
        "type": "object",
        "required": [
          "event_type",
          "timestamp"
        ],
        "title": "BeaconEvent",
        "description": "A single analytics event from the frontend beacon."
      },
      "BetaFeatureListItem": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "status": {
            "type": "string",
            "enum": [
              "hidden",
              "beta",
              "ga"
            ],
            "title": "Status"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "True if the current user has opted in to this feature."
          }
        },
        "type": "object",
        "required": [
          "slug",
          "name",
          "description",
          "status",
          "created_at",
          "enabled"
        ],
        "title": "BetaFeatureListItem",
        "description": "A single beta feature as returned in a list, decorated with the\nrequesting user's opt-in state.\n\nFlattens BetaFeatureResponse fields directly (no nesting) so the client\ncan render a feature row without unpacking a nested object.\n\nNote: ``from_attributes`` ORM-mode is intentionally NOT set here.  The\n``enabled`` field is a computed value derived from a join with\n``user_beta_features`` — it has no corresponding column on the\n``BetaFeature`` ORM model.  Callers must always construct this schema\nwith an explicit ``enabled=`` keyword argument; calling\n``BetaFeatureListItem.model_validate(orm_obj)`` on a bare ``BetaFeature``\ninstance will raise ``ValidationError: enabled - Field required``."
      },
      "BetaFeatureListResponse": {
        "properties": {
          "features": {
            "items": {
              "$ref": "#/components/schemas/BetaFeatureListItem"
            },
            "type": "array",
            "title": "Features",
            "description": "List of beta features visible to the requesting user."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of features in the result set."
          }
        },
        "type": "object",
        "required": [
          "features",
          "total"
        ],
        "title": "BetaFeatureListResponse",
        "description": "Paginated list of beta features with per-feature opt-in flags.\n\n``features`` contains only features with status 'beta' or 'ga' for\nregular users; admin endpoints may return 'hidden' features as well."
      },
      "BetaFeatureMyResponse": {
        "properties": {
          "features": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Features",
            "description": "Sorted list of feature slugs accessible to the requesting user.  Includes all GA features and any beta features the user has enabled."
          }
        },
        "type": "object",
        "required": [
          "features"
        ],
        "title": "BetaFeatureMyResponse",
        "description": "Response for GET /my — lightweight slug list for frontend feature checks.\n\nReturns only the slugs the authenticated user has access to (GA features\nplus beta features they have opted in to).  Sorted alphabetically."
      },
      "BetaFeatureToggleResponse": {
        "properties": {
          "feature_slug": {
            "type": "string",
            "title": "Feature Slug",
            "description": "Slug of the feature that was toggled."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "True if the feature is now enabled; false if it was disabled."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable confirmation message, e.g. 'Feature enabled.'"
          }
        },
        "type": "object",
        "required": [
          "feature_slug",
          "enabled",
          "message"
        ],
        "title": "BetaFeatureToggleResponse",
        "description": "Confirmation returned after a user enables or disables a beta feature."
      },
      "BillingAddress": {
        "properties": {
          "line1": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Line1"
          },
          "line2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Line2"
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "state": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "State"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Postal Code"
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code, e.g. 'RO', 'US'."
          }
        },
        "type": "object",
        "title": "BillingAddress",
        "description": "Stripe Address shape. All fields optional — a partial address is valid."
      },
      "BillingDetails": {
        "properties": {
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          },
          "tier_used": {
            "type": "string",
            "title": "Tier Used"
          },
          "byop_applied": {
            "type": "boolean",
            "title": "Byop Applied",
            "description": "Whether BYOP discount was applied to this request",
            "default": false
          },
          "byop_discount_percent": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Byop Discount Percent",
            "description": "BYOP discount percentage applied (e.g., 98.4 for 98.4% off)"
          },
          "original_cost_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Original Cost Microcents",
            "description": "Original cost before BYOP discount in microcents"
          },
          "final_cost_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Final Cost Microcents",
            "description": "Final cost after BYOP discount in microcents"
          },
          "byos_applied": {
            "type": "boolean",
            "title": "Byos Applied",
            "description": "Whether BYOS session cookies were injected into this request",
            "default": false
          },
          "byos_session_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Byos Session Name",
            "description": "Name of the stored session used (e.g. 'My Amazon Prime')"
          },
          "method_surcharge_applied": {
            "type": "boolean",
            "title": "Method Surcharge Applied",
            "description": "Whether a method surcharge was applied (POST costs 1.5x base tier)",
            "default": false
          },
          "method_surcharge_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method Surcharge Microcents",
            "description": "Additional cost from the HTTP method surcharge in microcents. POST incurs a 1.5x multiplier — this field shows the extra amount charged above the base tier cost."
          }
        },
        "type": "object",
        "required": [
          "total_credits",
          "tier_used"
        ],
        "title": "BillingDetails",
        "description": "Detailed billing breakdown for a scrape request."
      },
      "BillingIdentityResponse": {
        "properties": {
          "legal_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Legal Name"
          },
          "billing_address": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BillingAddress"
              },
              {
                "type": "null"
              }
            ]
          },
          "tax_ids": {
            "items": {
              "$ref": "#/components/schemas/BillingTaxIdEntry"
            },
            "type": "array",
            "title": "Tax Ids"
          },
          "stripe_customer_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stripe Customer Id"
          }
        },
        "type": "object",
        "title": "BillingIdentityResponse",
        "description": "Response body for GET/PUT .../billing-identity."
      },
      "BillingIdentityUpdate": {
        "properties": {
          "legal_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Legal Name"
          },
          "billing_address": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BillingAddress"
              },
              {
                "type": "null"
              }
            ]
          },
          "tax_ids": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/BillingTaxIdInput"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Ids"
          }
        },
        "type": "object",
        "title": "BillingIdentityUpdate",
        "description": "Request body for PUT .../billing-identity.\n\nAll fields optional — a caller updates only what they send. `tax_ids`,\nwhen present, REPLACES the full set (matching how the UI form works: it\nalways submits the complete current list, not a diff). Send an empty\nlist to clear all tax IDs."
      },
      "BillingTaxIdEntry": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Stripe tax ID type, e.g. 'eu_vat', 'us_ein', 'gb_vat'. See https://stripe.com/docs/api/tax_ids/object#tax_id_object-type for the full enum."
          },
          "value": {
            "type": "string",
            "title": "Value"
          },
          "verification_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Verification Status",
            "description": "Stripe verification status: 'pending', 'verified', 'unverified', or 'unavailable'. Null until Stripe has attempted verification."
          }
        },
        "type": "object",
        "required": [
          "type",
          "value"
        ],
        "title": "BillingTaxIdEntry",
        "description": "A stored tax ID, including Stripe's verification status."
      },
      "BillingTaxIdInput": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Stripe tax ID type, e.g. 'eu_vat', 'us_ein', 'gb_vat'. See https://stripe.com/docs/api/tax_ids/object#tax_id_object-type for the full enum."
          },
          "value": {
            "type": "string",
            "title": "Value"
          }
        },
        "type": "object",
        "required": [
          "type",
          "value"
        ],
        "title": "BillingTaxIdInput",
        "description": "A tax ID to add. Mirrors the `type`/`value` pair Stripe's tax_id_data accepts."
      },
      "Body_import_contacts_csv_api_v1_contact_lists__list_id__import_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "CSV file with an 'email' column header"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_import_contacts_csv_api_v1_contact_lists__list_id__import_post"
      },
      "Body_upload_attachment_api_v1_support_upload_post": {
        "properties": {
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File"
          }
        },
        "type": "object",
        "required": [
          "file"
        ],
        "title": "Body_upload_attachment_api_v1_support_upload_post"
      },
      "Body_upload_connector_api_v1_connectors_post": {
        "properties": {
          "slug": {
            "type": "string",
            "maxLength": 60,
            "minLength": 2,
            "pattern": "^[a-z0-9][a-z0-9_\\-]*$",
            "title": "Slug",
            "description": "Unique lowercase slug for this connector (per user)."
          },
          "file": {
            "type": "string",
            "contentMediaType": "application/octet-stream",
            "title": "File",
            "description": "Zip archive containing connector.py"
          }
        },
        "type": "object",
        "required": [
          "slug",
          "file"
        ],
        "title": "Body_upload_connector_api_v1_connectors_post"
      },
      "BulkAdResult": {
        "properties": {
          "position": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Position",
            "description": "1-indexed position within the ad slot."
          },
          "slot": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Slot",
            "description": "Ad slot: 'top' (#tads), 'bottom' (#bottomads), or null for shopping ads."
          },
          "display_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Url",
            "description": "Green display URL shown on the ad."
          },
          "destination_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Destination Url",
            "description": "Actual click-through destination URL."
          },
          "advertiser_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Name",
            "description": "Advertiser legal name from Google's Ad Transparency Center."
          },
          "advertiser_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Country",
            "description": "Advertiser's registered country."
          },
          "advertiser_link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Link",
            "description": "Link to the advertiser's Ad Transparency profile."
          },
          "profile_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Id",
            "description": "Advertiser profile ID (AR-format). Null when ATC fallback was used."
          },
          "adstransparency_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Adstransparency Url",
            "description": "Full 'See more ads this advertiser has shown' link from the 'About this advertiser' panel. Null on the flat response shape or when batchexecute was not used (#28376)."
          },
          "funded_by": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Funded By",
            "description": "'Ad funded by' entity — the payer, distinct from advertiser_name (equals it when the advertiser self-funds). Null when absent (#28376)."
          },
          "identity_verified": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Identity Verified",
            "description": "True when Google reports 'Advertiser identity verified by Google'; False when explicitly unverified; null when absent (#28376)."
          },
          "targeting_reasons": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Targeting Reasons",
            "description": "Reason codes explaining why Google served this ad (e.g. 'current_search_terms', 'gender', 'age'). Empty when unknown."
          },
          "is_demographic_ad": {
            "type": "boolean",
            "title": "Is Demographic Ad",
            "description": "True when any targeting_reasons entry is a demographic code (gender/age/etc.). False for purely contextual ads.",
            "default": false
          }
        },
        "type": "object",
        "title": "BulkAdResult",
        "description": "One extracted ad within a bulk job's results preview (#28372).\n\nMirrors the ad-dict shape produced by ``_build_download_row`` /\n``worker.b2b_delivery.build_delivery_rows`` (the eight advertiser-identity\nfields) plus the two ad-transparency fields the dashboard needs to explain\n*why* an ad was shown: ``targeting_reasons`` and ``is_demographic_ad``.\nAll fields are optional/defaulted so partial or pre-#28175 ads still\nserialize cleanly."
      },
      "BulkJobItem": {
        "properties": {
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Url",
            "description": "Target URL to scrape.  Mutually exclusive with ``query``.  Must begin with http:// or https://.  Max 2048 characters."
          },
          "query": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Query",
            "description": "SERP search query string.  Mutually exclusive with ``url``.  When set, the job is dispatched as a search job (job_type='search') to the SERP pipeline rather than the scrape pipeline.  Max 500 characters."
          },
          "engine": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "duckduckgo",
                  "google",
                  "bing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "Search engine to use for query-type jobs.  Accepted values: 'duckduckgo' (default when omitted), 'google', 'bing'.  Only valid when ``query`` is set; rejected with 422 if sent alongside ``url``."
          },
          "num_results": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 30.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Num Results",
            "description": "Number of organic results to return per query-type job (1–30).  Defaults to 10 when omitted.  Only valid when ``query`` is set; rejected with 422 if sent alongside ``url``."
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Two-letter ISO 3166-1 alpha-2 country code for geo-targeted search results (e.g. 'us', 'gb', 'de').  Only valid when ``query`` is set; rejected with 422 if sent alongside ``url``."
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "BCP 47 language tag for search results (e.g. 'en', 'de', 'fr').  Only valid when ``query`` is set; rejected with 422 if sent alongside ``url``."
          },
          "session_pool_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Pool Id",
            "description": "Demographic session pool identifier for B2B routing (#20410).  When set, overrides ``tenant_id`` as the pool key passed to ``SerpSessionPool.acquire_session()``, routing the search through the demographically-targeted browser session for this profile.  Use the ``profile_id`` returned by POST /api/v1/b2b/profiles once ``status == 'complete'``.  Only valid when ``query`` is set; rejected with 422 if sent alongside ``url``."
          },
          "pipeline_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-z0-9]([a-z0-9_-]*[a-z0-9])?$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pipeline Id",
            "description": "Pipeline configuration ID to apply (from b2b_tenant_pipeline_configs). If omitted, the tenant's default active pipeline is used."
          },
          "safe_search": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Safe Search",
            "description": "Override Google safe search filtering for this job. None (default): uses the platform default (safe=active). False: disables safe search (omits safe=active from the Google URL) — recommended for ad-focused B2B tenants (e.g. ad-fraud detection) where safe=active is an automated-tool fingerprint and may suppress ad delivery. True: explicitly enables safe search (safe=active). Only affects Google SERP jobs; DDG Lite uses a separate p= parameter."
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Arbitrary key-value metadata attached to this job for client tracking."
          }
        },
        "type": "object",
        "title": "BulkJobItem",
        "description": "A single job spec within a bulk submission.\n\nExactly one of ``url`` (scrape job) or ``query`` (SERP search job) must be\nprovided.  They are mutually exclusive — supplying both or neither raises a\nvalidation error."
      },
      "BulkJobListItem": {
        "properties": {
          "bulk_id": {
            "type": "string",
            "title": "Bulk Id",
            "description": "The bulk submission idempotency key."
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id",
            "description": "Organization ID the submission is bound to."
          },
          "job_count": {
            "type": "integer",
            "title": "Job Count",
            "description": "Total jobs in this submission."
          },
          "jobs_released": {
            "type": "integer",
            "title": "Jobs Released",
            "description": "Number of jobs released from holding set to main worker queue so far.",
            "default": 0
          },
          "jobs_pending": {
            "type": "integer",
            "title": "Jobs Pending",
            "description": "Number of jobs still waiting in the holding set.",
            "default": 0
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Lifecycle status: 'accepted' | 'draining' | 'completed' | 'failed' | 'burst_rejected'. 'burst_rejected' is transient — the burst limit was exceeded at submission time; the tenant may retry."
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "title": "Submitted At",
            "description": "When the bulk submission was received."
          },
          "estimated_completion_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Completion At",
            "description": "Estimated completion time based on original rate shape config."
          }
        },
        "type": "object",
        "required": [
          "bulk_id",
          "tenant_id",
          "job_count",
          "status",
          "submitted_at"
        ],
        "title": "BulkJobListItem",
        "description": "Single row in a paginated bulk job list response.\n\nMirrors ``BulkJobStatus`` but omits ``rate_shape_config`` to keep the list\npayload compact — callers that need the full rate shape can fetch individual\nrecords via ``GET /api/v1/b2b/jobs/bulk/{bulk_id}``."
      },
      "BulkJobListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/BulkJobListItem"
            },
            "type": "array",
            "title": "Items",
            "description": "Bulk submissions for this tenant, ordered by submitted_at DESC."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of submissions for this tenant (across all pages)."
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Page size used for this response."
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Offset used for this response."
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "True if there are more submissions beyond this page."
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "title": "BulkJobListResponse",
        "description": "Paginated response body for GET /api/v1/b2b/jobs."
      },
      "BulkJobRequest": {
        "properties": {
          "bulk_id": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Bulk Id",
            "description": "Client-supplied idempotency key for this submission. Re-submitting an identical bulk_id returns the existing bulk submission status without re-enqueuing any jobs."
          },
          "jobs": {
            "items": {
              "$ref": "#/components/schemas/BulkJobItem"
            },
            "type": "array",
            "maxItems": 100000,
            "minItems": 1,
            "title": "Jobs",
            "description": "Array of job specs to submit."
          },
          "rate_shape_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RateShapeConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Throughput control parameters. If omitted, tenant defaults from tenant_config are used."
          }
        },
        "type": "object",
        "required": [
          "bulk_id",
          "jobs"
        ],
        "title": "BulkJobRequest",
        "description": "Request body for POST /api/v1/b2b/jobs/bulk."
      },
      "BulkJobResponse": {
        "properties": {
          "bulk_id": {
            "type": "string",
            "title": "Bulk Id",
            "description": "The bulk submission idempotency key."
          },
          "job_count": {
            "type": "integer",
            "title": "Job Count",
            "description": "Number of jobs accepted into the holding set."
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id",
            "description": "Organization ID the jobs are bound to (for audit trail)."
          },
          "estimated_completion_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Completion At",
            "description": "Estimated wall-clock time when all jobs will have been released from the holding set and executed, based on rate_shape_config.jobs_per_hour."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Submission status: 'accepted' for new submissions; 'duplicate' for idempotent replay of an existing in-flight or completed submission; 'failed' when a previous attempt with the same bulk_id reached the DB audit step but failed to write to Redis — the client should treat this as a hard failure and use a new bulk_id to resubmit.",
            "default": "accepted"
          }
        },
        "type": "object",
        "required": [
          "bulk_id",
          "job_count",
          "tenant_id"
        ],
        "title": "BulkJobResponse",
        "description": "Response body for POST /api/v1/b2b/jobs/bulk."
      },
      "BulkJobResultItem": {
        "properties": {
          "job_id": {
            "type": "string",
            "format": "uuid",
            "title": "Job Id",
            "description": "UUID of the jobs row."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Job status: 'queued' | 'running' | 'succeeded' | 'failed' | 'rejected'."
          },
          "domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain",
            "description": "Target domain scraped (e.g. 'google.com').  Null until job completes."
          },
          "tier_used": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier Used",
            "description": "Anti-bot tier used ('1'–'4').  Null until job completes."
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "Search query from the original job payload (#28372).  Empty if absent.",
            "default": ""
          },
          "demographic_profile_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Demographic Profile Id",
            "description": "Demographic profile ID used to target this query, from the job payload (#28372).  Null when the query used no demographic profile."
          },
          "ads": {
            "items": {
              "$ref": "#/components/schemas/BulkAdResult"
            },
            "type": "array",
            "title": "Ads",
            "description": "Structured, untruncated ad-identity results for this job (#28372).  Empty list when the job had no ads or has not completed."
          },
          "ad_count": {
            "type": "integer",
            "title": "Ad Count",
            "description": "len(ads) — number of ads found for this job (#28372).",
            "default": 0
          },
          "result_preview": {
            "anyOf": [
              {},
              {
                "type": "null"
              }
            ],
            "title": "Result Preview",
            "description": "JSONB result truncated to first 2 KB (JSON-serialized string).  Only present when status == 'succeeded'.  Full results are available via S3 delivery."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message when status == 'failed'.  Null otherwise."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the job row was created."
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At",
            "description": "When the job completed (succeeded or failed).  Null for in-flight jobs."
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "status",
          "created_at"
        ],
        "title": "BulkJobResultItem",
        "description": "A single job row in the bulk results preview response.\n\n``result_preview`` is truncated to 2 KB on the server side — enterprise\nclients needing the full raw JSONB should use S3 delivery or the JSONL\ndownload.  ``ads`` carries the structured, untruncated ad-identity rows the\ndashboard renders (#28372).  ``error`` is only present when\nstatus == 'failed'."
      },
      "BulkJobResultsResponse": {
        "properties": {
          "bulk_id": {
            "type": "string",
            "title": "Bulk Id",
            "description": "The bulk submission idempotency key."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of job rows linked to this bulk submission."
          },
          "page": {
            "type": "integer",
            "title": "Page",
            "description": "Current page number (1-indexed)."
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size",
            "description": "Number of items per page."
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/BulkJobResultItem"
            },
            "type": "array",
            "title": "Items",
            "description": "Job result items for the current page."
          },
          "summary": {
            "$ref": "#/components/schemas/BulkResultsSummary",
            "description": "Page-scoped ad aggregate counts (#28372)."
          },
          "data_note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Data Note",
            "description": "Present when job rows are available but some are not linked to this bulk submission.  Jobs submitted before the FK migration (2026-07-02) have NULL bulk_submission_id and are excluded from this response.  Results preview only covers jobs submitted after migration 0250 was applied."
          }
        },
        "type": "object",
        "required": [
          "bulk_id",
          "total",
          "page",
          "page_size",
          "items"
        ],
        "title": "BulkJobResultsResponse",
        "description": "Response body for GET /api/v1/b2b/jobs/bulk/{bulk_id}/results."
      },
      "BulkJobStatus": {
        "properties": {
          "bulk_id": {
            "type": "string",
            "title": "Bulk Id",
            "description": "The bulk submission idempotency key."
          },
          "tenant_id": {
            "type": "string",
            "title": "Tenant Id",
            "description": "Organization ID the submission is bound to."
          },
          "job_count": {
            "type": "integer",
            "title": "Job Count",
            "description": "Total jobs in this submission."
          },
          "jobs_released": {
            "type": "integer",
            "title": "Jobs Released",
            "description": "Number of jobs released from holding set to main worker queue so far.",
            "default": 0
          },
          "jobs_pending": {
            "type": "integer",
            "title": "Jobs Pending",
            "description": "Number of jobs still waiting in the holding set.",
            "default": 0
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Lifecycle status: 'accepted' | 'draining' | 'completed' | 'failed' | 'burst_rejected'. 'burst_rejected' is transient — the burst limit was exceeded at submission time; the tenant may retry."
          },
          "submitted_at": {
            "type": "string",
            "format": "date-time",
            "title": "Submitted At",
            "description": "When the bulk submission was received."
          },
          "estimated_completion_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Completion At",
            "description": "Estimated completion time based on original rate shape config."
          },
          "rate_shape_config": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Shape Config",
            "description": "Rate shape config applied to this submission."
          }
        },
        "type": "object",
        "required": [
          "bulk_id",
          "tenant_id",
          "job_count",
          "status",
          "submitted_at"
        ],
        "title": "BulkJobStatus",
        "description": "Response body for GET /api/v1/b2b/jobs/bulk/{bulk_id}."
      },
      "BulkResultsSummary": {
        "properties": {
          "total_ads": {
            "type": "integer",
            "title": "Total Ads",
            "description": "Total ads across all items on this page.",
            "default": 0
          },
          "demographic_ads": {
            "type": "integer",
            "title": "Demographic Ads",
            "description": "Ads on this page with is_demographic_ad == true.",
            "default": 0
          },
          "unique_advertisers": {
            "type": "integer",
            "title": "Unique Advertisers",
            "description": "Distinct non-empty advertiser_name values on this page.",
            "default": 0
          }
        },
        "type": "object",
        "title": "BulkResultsSummary",
        "description": "Aggregate ad counts for the current results page (#28372).\n\nCounts are scoped to the items returned on the current page — not the\nentire bulk submission — so callers paginating through results should sum\nacross pages for a submission-wide total. Documented as page-scoped to\navoid implying a cross-page aggregate the preview endpoint does not compute."
      },
      "BuyerPurchaseItem": {
        "properties": {
          "sale_id": {
            "type": "string",
            "title": "Sale Id"
          },
          "template_id": {
            "type": "string",
            "title": "Template Id"
          },
          "template_name": {
            "type": "string",
            "title": "Template Name"
          },
          "template_slug": {
            "type": "string",
            "title": "Template Slug"
          },
          "price_cents": {
            "type": "integer",
            "title": "Price Cents"
          },
          "purchased_at": {
            "type": "string",
            "title": "Purchased At"
          },
          "forked_workflow_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Forked Workflow Id"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "last_run_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run Status"
          },
          "creator_display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Creator Display Name"
          },
          "creator_storefront_slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Creator Storefront Slug"
          }
        },
        "type": "object",
        "required": [
          "sale_id",
          "template_id",
          "template_name",
          "template_slug",
          "price_cents",
          "purchased_at",
          "forked_workflow_id",
          "run_count",
          "last_run_at",
          "last_run_status",
          "creator_display_name",
          "creator_storefront_slug"
        ],
        "title": "BuyerPurchaseItem",
        "description": "Single template purchase from the buyer's perspective."
      },
      "BuyerPurchasesResponse": {
        "properties": {
          "purchases": {
            "items": {
              "$ref": "#/components/schemas/BuyerPurchaseItem"
            },
            "type": "array",
            "title": "Purchases"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "purchases",
          "total"
        ],
        "title": "BuyerPurchasesResponse",
        "description": "Response for GET /buyer/purchases."
      },
      "BuyerRunsResponse": {
        "properties": {
          "sale_id": {
            "type": "string",
            "title": "Sale Id"
          },
          "template_name": {
            "type": "string",
            "title": "Template Name"
          },
          "forked_workflow_id": {
            "type": "string",
            "title": "Forked Workflow Id"
          },
          "runs": {
            "items": {
              "$ref": "#/components/schemas/RunSummary"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "sale_id",
          "template_name",
          "forked_workflow_id",
          "runs",
          "total"
        ],
        "title": "BuyerRunsResponse",
        "description": "Response for GET /buyer/purchases/{sale_id}/runs."
      },
      "BuyerSubscriptionItem": {
        "properties": {
          "subscription_id": {
            "type": "string",
            "title": "Subscription Id"
          },
          "plan_id": {
            "type": "string",
            "title": "Plan Id"
          },
          "plan_name": {
            "type": "string",
            "title": "Plan Name"
          },
          "monthly_price_cents": {
            "type": "integer",
            "title": "Monthly Price Cents"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "canceled_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Canceled At"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "creator_display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Creator Display Name"
          },
          "creator_storefront_slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Creator Storefront Slug"
          }
        },
        "type": "object",
        "required": [
          "subscription_id",
          "plan_id",
          "plan_name",
          "monthly_price_cents",
          "status",
          "current_period_end",
          "canceled_at",
          "created_at",
          "creator_display_name",
          "creator_storefront_slug"
        ],
        "title": "BuyerSubscriptionItem",
        "description": "Single creator subscription from the buyer's perspective."
      },
      "BuyerSubscriptionsResponse": {
        "properties": {
          "subscriptions": {
            "items": {
              "$ref": "#/components/schemas/BuyerSubscriptionItem"
            },
            "type": "array",
            "title": "Subscriptions"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "subscriptions",
          "total"
        ],
        "title": "BuyerSubscriptionsResponse",
        "description": "Response for GET /buyer/subscriptions."
      },
      "ByopFeedbackEvent": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id",
            "description": "SERP job identifier for correlation."
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "Search query (truncated to 100 chars)."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Outcome of the SERP request. Values: 'success' (organic results returned), 'blocked' (Google returned zero organic results), 'failed' (network/timeout/error before any result)."
          },
          "block_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Block Reason",
            "description": "Narrows the block type when status is 'blocked' or 'failed'. Values: 'search_guard' (Google search-guard / consent interstitial), 'captcha' (CAPTCHA challenge detected), 'rate_limited' (HTTP 429 or rate-limit body), 'no_results' (pages returned but empty), 'timeout' (asyncio.TimeoutError), 'error' (other exception), null (success, or parallel-engine path with insufficient signal)."
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Requested ISO 3166-1 alpha-2 geo (e.g. 'GB'). Use for per-country waterfall routing. Null when no explicit geo was requested."
          },
          "session_pool_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Pool Id",
            "description": "Demographic profile pool id (e.g. persona UUID) for this request. Null for non-demographic requests."
          },
          "ts": {
            "type": "string",
            "title": "Ts",
            "description": "ISO 8601 UTC timestamp when the event was recorded."
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "query",
          "status",
          "ts"
        ],
        "title": "ByopFeedbackEvent",
        "description": "A single BYOP proxy outcome event returned by GET /api/v1/b2b/proxy/feedback.\n\nEvents are pushed to Redis by the worker after each SERP request and\nconsumed atomically by the polling endpoint.  Once popped they are gone —\nthe caller must process them before the next poll."
      },
      "ByopFeedbackResponse": {
        "properties": {
          "events": {
            "items": {
              "$ref": "#/components/schemas/ByopFeedbackEvent"
            },
            "type": "array",
            "title": "Events",
            "description": "Proxy outcome events, ordered oldest-first. Empty list when no events are queued."
          },
          "count": {
            "type": "integer",
            "title": "Count",
            "description": "Number of events returned in this response."
          }
        },
        "type": "object",
        "required": [
          "events",
          "count"
        ],
        "title": "ByopFeedbackResponse",
        "description": "Response body for GET /api/v1/b2b/proxy/feedback.\n\nEvents are returned oldest-first and are atomically removed from the Redis\nqueue on retrieval — they will not appear in subsequent polls."
      },
      "CategoryListResponse": {
        "properties": {
          "categories": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__support__CategoryResponse"
            },
            "type": "array",
            "title": "Categories"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "categories",
          "total"
        ],
        "title": "CategoryListResponse",
        "description": "Response for listing all active categories."
      },
      "ChangeListResponse": {
        "properties": {
          "changes": {
            "items": {
              "$ref": "#/components/schemas/ChangeResponse"
            },
            "type": "array",
            "title": "Changes"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "changes",
          "total"
        ],
        "title": "ChangeListResponse",
        "description": "List of changes."
      },
      "ChangePasswordRequest": {
        "properties": {
          "current_password": {
            "type": "string",
            "title": "Current Password"
          },
          "new_password": {
            "type": "string",
            "title": "New Password"
          }
        },
        "type": "object",
        "required": [
          "current_password",
          "new_password"
        ],
        "title": "ChangePasswordRequest",
        "description": "Change password request."
      },
      "ChangeResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "previous_snapshot_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Snapshot Id"
          },
          "current_snapshot_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Snapshot Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "change_type": {
            "type": "string",
            "title": "Change Type"
          },
          "diff": {
            "additionalProperties": true,
            "type": "object",
            "title": "Diff"
          },
          "notified": {
            "type": "boolean",
            "title": "Notified"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "url",
          "change_type",
          "diff",
          "notified",
          "created_at"
        ],
        "title": "ChangeResponse",
        "description": "Detected change between snapshots."
      },
      "ChangeSummary": {
        "properties": {
          "new_pages": {
            "type": "integer",
            "title": "New Pages",
            "description": "Pages not seen in the previous crawl",
            "default": 0
          },
          "changed_pages": {
            "type": "integer",
            "title": "Changed Pages",
            "description": "Pages whose content hash changed",
            "default": 0
          },
          "unchanged_pages": {
            "type": "integer",
            "title": "Unchanged Pages",
            "description": "Pages with identical content",
            "default": 0
          },
          "removed_pages": {
            "type": "integer",
            "title": "Removed Pages",
            "description": "Pages present in previous crawl but missing from current one",
            "default": 0
          },
          "removed_urls": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Removed Urls",
            "description": "URLs that were in the previous crawl but not in this one"
          }
        },
        "type": "object",
        "title": "ChangeSummary",
        "description": "Crawl-level aggregation of page changes."
      },
      "ChangeTrackingConfig": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Enable change detection against the previous crawl with the same tracking_id",
            "default": false
          },
          "tracking_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Tracking Id",
            "description": "Identifier for this tracking history. Allows parallel tracking tracks for the same domain (e.g., 'daily-price-check'). Auto-generated from the crawl domain if omitted."
          },
          "mode": {
            "type": "string",
            "enum": [
              "content",
              "structured"
            ],
            "title": "Mode",
            "description": "'content' — SHA-256 hash of normalized text for fast comparison. 'structured' — JSON field-level diff on extraction results.",
            "default": "content"
          },
          "include_diff": {
            "type": "boolean",
            "title": "Include Diff",
            "description": "Include the actual diff output in the response. Adds +1 credit/page for content mode, +2 for structured mode.",
            "default": false
          }
        },
        "type": "object",
        "title": "ChangeTrackingConfig",
        "description": "Configuration for cross-crawl change detection."
      },
      "ChatAction": {
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "workflow_create",
              "workflow_update",
              "cost_estimate",
              "scrape_preview",
              "site_discovery"
            ],
            "title": "Type",
            "description": "Action type"
          },
          "data": {
            "additionalProperties": true,
            "type": "object",
            "title": "Data",
            "description": "Action payload"
          }
        },
        "type": "object",
        "required": [
          "type"
        ],
        "title": "ChatAction",
        "description": "An action the AI suggests (e.g., creating a workflow)."
      },
      "ChatRequest": {
        "properties": {
          "message": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 1,
            "title": "Message",
            "description": "User's natural language message"
          },
          "conversation_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64
              },
              {
                "type": "null"
              }
            ],
            "title": "Conversation Id",
            "description": "Conversation ID for multi-turn context. Omit to start new."
          },
          "context": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChatWorkflowContext"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional workflow editor context"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "ChatRequest",
        "description": "Request body for POST /api/v1/chat."
      },
      "ChatResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Assistant's text response"
          },
          "conversation_id": {
            "type": "string",
            "title": "Conversation Id",
            "description": "Conversation ID for follow-up messages"
          },
          "actions": {
            "items": {
              "$ref": "#/components/schemas/ChatAction"
            },
            "type": "array",
            "title": "Actions",
            "description": "Suggested actions (workflow creation, etc.)"
          },
          "tool_calls": {
            "items": {
              "$ref": "#/components/schemas/ChatToolCallInfo"
            },
            "type": "array",
            "title": "Tool Calls",
            "description": "Tools invoked during this response"
          },
          "usage": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Usage",
            "description": "Token usage info"
          }
        },
        "type": "object",
        "required": [
          "message",
          "conversation_id"
        ],
        "title": "ChatResponse",
        "description": "Response body for POST /api/v1/chat (non-streaming)."
      },
      "ChatToolCallInfo": {
        "properties": {
          "tool": {
            "type": "string",
            "title": "Tool",
            "description": "Tool name"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "success",
              "error"
            ],
            "title": "Status",
            "description": "Execution status"
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Summary",
            "description": "Brief result summary"
          },
          "elapsed_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Elapsed Ms",
            "description": "Execution time in ms"
          }
        },
        "type": "object",
        "required": [
          "tool",
          "status"
        ],
        "title": "ChatToolCallInfo",
        "description": "Summary of a tool call made during the response."
      },
      "ChatWorkflowContext": {
        "properties": {
          "workflow_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Workflow Id"
          },
          "graph": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Graph"
          },
          "selected_node_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Selected Node Id"
          }
        },
        "type": "object",
        "title": "ChatWorkflowContext",
        "description": "Optional context from the visual workflow editor."
      },
      "CheckoutRequest": {
        "properties": {
          "price_id": {
            "type": "string",
            "title": "Price Id"
          },
          "success_url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Success Url"
          },
          "cancel_url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Cancel Url"
          },
          "mode": {
            "type": "string",
            "title": "Mode",
            "default": "subscription"
          }
        },
        "type": "object",
        "required": [
          "price_id",
          "success_url",
          "cancel_url"
        ],
        "title": "CheckoutRequest",
        "description": "Checkout session creation request."
      },
      "CheckoutResponse": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "url"
        ],
        "title": "CheckoutResponse",
        "description": "Checkout session response."
      },
      "ClickAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "click",
            "title": "Type",
            "default": "click"
          },
          "selector": {
            "type": "string",
            "maxLength": 500,
            "title": "Selector",
            "description": "CSS selector of element to click"
          }
        },
        "type": "object",
        "required": [
          "selector"
        ],
        "title": "ClickAction",
        "description": "Click an element matching a CSS selector."
      },
      "CommentCreate": {
        "properties": {
          "post_id": {
            "type": "string",
            "format": "uuid",
            "title": "Post Id"
          },
          "parent_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Id"
          },
          "content": {
            "type": "string",
            "maxLength": 5000,
            "minLength": 1,
            "title": "Content"
          },
          "author_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Name"
          },
          "author_email": {
            "anyOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Email"
          },
          "author_website": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Website"
          },
          "website_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Website Url"
          }
        },
        "type": "object",
        "required": [
          "post_id",
          "content"
        ],
        "title": "CommentCreate"
      },
      "CommentResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "post_id": {
            "type": "string",
            "format": "uuid",
            "title": "Post Id"
          },
          "parent_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Parent Id"
          },
          "author_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Name"
          },
          "author_website": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Website"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "content": {
            "type": "string",
            "title": "Content"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "likes": {
            "type": "integer",
            "title": "Likes",
            "default": 0
          },
          "replies": {
            "items": {
              "$ref": "#/components/schemas/CommentResponse"
            },
            "type": "array",
            "title": "Replies",
            "default": []
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "post_id",
          "content",
          "status",
          "created_at",
          "updated_at"
        ],
        "title": "CommentResponse"
      },
      "CompleteLinkPublicRequest": {
        "properties": {
          "state": {
            "type": "string",
            "title": "State"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          },
          "provider_account_id": {
            "type": "string",
            "title": "Provider Account Id"
          },
          "provider_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider Email"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          }
        },
        "type": "object",
        "required": [
          "state",
          "provider",
          "provider_account_id"
        ],
        "title": "CompleteLinkPublicRequest",
        "description": "Request to complete OAuth account linking (public endpoint, uses state for auth)."
      },
      "CompleteLinkRequest": {
        "properties": {
          "state": {
            "type": "string",
            "title": "State"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          },
          "provider_account_id": {
            "type": "string",
            "title": "Provider Account Id"
          },
          "provider_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider Email"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          }
        },
        "type": "object",
        "required": [
          "state",
          "provider",
          "provider_account_id"
        ],
        "title": "CompleteLinkRequest",
        "description": "Request to complete OAuth account linking (requires auth)."
      },
      "CompleteSignUpRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "code": {
            "type": "string",
            "title": "Code"
          },
          "device_fingerprint": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeviceFingerprint"
              },
              {
                "type": "null"
              }
            ]
          },
          "attribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AttributionData"
              },
              {
                "type": "null"
              }
            ]
          },
          "anonymous_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Anonymous Id"
          },
          "ref_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ref Code"
          }
        },
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "title": "CompleteSignUpRequest",
        "description": "Request to complete signup with OTP verification."
      },
      "ConnectResponse": {
        "properties": {
          "authorization_url": {
            "type": "string",
            "title": "Authorization Url"
          },
          "state": {
            "type": "string",
            "title": "State"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          }
        },
        "type": "object",
        "required": [
          "authorization_url",
          "state",
          "provider"
        ],
        "title": "ConnectResponse",
        "description": "Response from the connect initiation endpoint."
      },
      "ConnectStatusResponse": {
        "properties": {
          "has_connect_account": {
            "type": "boolean",
            "title": "Has Connect Account"
          },
          "onboarding_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Onboarding Status"
          },
          "kyc_verified": {
            "type": "boolean",
            "title": "Kyc Verified",
            "default": false
          },
          "payout_eligible": {
            "type": "boolean",
            "title": "Payout Eligible",
            "default": false
          },
          "eligibility_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Eligibility Reason"
          },
          "pending_balance_cents": {
            "type": "integer",
            "title": "Pending Balance Cents",
            "default": 0
          },
          "country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "is_1099_eligible": {
            "type": "boolean",
            "title": "Is 1099 Eligible",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "has_connect_account"
        ],
        "title": "ConnectStatusResponse",
        "description": "GET /creator/connect/status response."
      },
      "ConnectionInfo": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Scopes"
          },
          "connected_at": {
            "type": "string",
            "format": "date-time",
            "title": "Connected At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "is_expired": {
            "type": "boolean",
            "title": "Is Expired"
          }
        },
        "type": "object",
        "required": [
          "id",
          "provider",
          "display_name",
          "scopes",
          "connected_at",
          "updated_at",
          "is_expired"
        ],
        "title": "ConnectionInfo",
        "description": "Public metadata for a connected provider (no tokens)."
      },
      "ConnectionListResponse": {
        "properties": {
          "connections": {
            "items": {
              "$ref": "#/components/schemas/ConnectionInfo"
            },
            "type": "array",
            "title": "Connections"
          }
        },
        "type": "object",
        "required": [
          "connections"
        ],
        "title": "ConnectionListResponse"
      },
      "ConnectorListResponse": {
        "properties": {
          "connectors": {
            "items": {
              "$ref": "#/components/schemas/ConnectorSummary"
            },
            "type": "array",
            "title": "Connectors"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "connectors",
          "total"
        ],
        "title": "ConnectorListResponse",
        "description": "Paginated list of user connectors."
      },
      "ConnectorStatus": {
        "type": "string",
        "enum": [
          "pending",
          "approved",
          "rejected"
        ],
        "title": "ConnectorStatus",
        "description": "Lifecycle status of an uploaded custom connector."
      },
      "ConnectorStatusResponse": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "status": {
            "$ref": "#/components/schemas/ConnectorStatus"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          }
        },
        "type": "object",
        "required": [
          "slug",
          "status",
          "error_message"
        ],
        "title": "ConnectorStatusResponse",
        "description": "Response for the GET .../status endpoint."
      },
      "ConnectorSummary": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "status": {
            "$ref": "#/components/schemas/ConnectorStatus"
          },
          "manifest": {
            "additionalProperties": true,
            "type": "object",
            "title": "Manifest"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "slug",
          "status",
          "manifest",
          "error_message",
          "created_at",
          "updated_at"
        ],
        "title": "ConnectorSummary",
        "description": "Lightweight connector representation returned in list responses."
      },
      "ConnectorUploadResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "status": {
            "$ref": "#/components/schemas/ConnectorStatus"
          },
          "manifest": {
            "additionalProperties": true,
            "type": "object",
            "title": "Manifest"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "slug",
          "status",
          "manifest",
          "created_at"
        ],
        "title": "ConnectorUploadResponse",
        "description": "Response returned after a successful connector upload."
      },
      "ConsentBasis": {
        "type": "string",
        "enum": [
          "legitimate_interest",
          "contract",
          "consent",
          "none"
        ],
        "title": "ConsentBasis",
        "description": "GDPR-lawful basis for sending marketing email."
      },
      "ContactCreate": {
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 320,
            "minLength": 3,
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "company": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Company"
          },
          "custom_fields": {
            "additionalProperties": true,
            "type": "object",
            "title": "Custom Fields"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "One of: new/contacted/replied/converted/bounced/unsubscribed",
            "default": "new"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "maxItems": 50,
            "title": "Tags"
          },
          "consent_basis": {
            "$ref": "#/components/schemas/ConsentBasis",
            "description": "GDPR/CCPA lawful basis for contacting this person",
            "default": "none"
          },
          "data_source": {
            "type": "string",
            "title": "Data Source",
            "description": "How this contact was collected: manual, csv_import, workflow, api",
            "default": "manual"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "URL where this person's data was collected (provenance)"
          },
          "source_workflow_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Workflow Id",
            "description": "Workflow that produced this contact"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "ContactCreate",
        "description": "Request to add a contact to a list.\n\nemail is normalised to lowercase on the server side regardless of what\nis submitted, matching the CHECK constraint in the contacts table."
      },
      "ContactItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "list_id": {
            "type": "string",
            "format": "uuid",
            "title": "List Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "company": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Company"
          },
          "custom_fields": {
            "additionalProperties": true,
            "type": "object",
            "title": "Custom Fields"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "consent_basis": {
            "type": "string",
            "title": "Consent Basis"
          },
          "data_source": {
            "type": "string",
            "title": "Data Source"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url"
          },
          "source_workflow_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Workflow Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "list_id",
          "email",
          "status",
          "consent_basis",
          "data_source",
          "created_at"
        ],
        "title": "ContactItem",
        "description": "A single contact with full provenance information."
      },
      "ContactListContentsResponse": {
        "properties": {
          "contacts": {
            "items": {
              "$ref": "#/components/schemas/ContactItem"
            },
            "type": "array",
            "title": "Contacts"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages"
          }
        },
        "type": "object",
        "required": [
          "contacts",
          "total",
          "page",
          "limit",
          "total_pages"
        ],
        "title": "ContactListContentsResponse",
        "description": "Paginated list of contacts within a single contact list."
      },
      "ContactListCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 200,
            "minLength": 1,
            "title": "Name",
            "description": "Display name for the list"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Optional description"
          },
          "processor_notice_accepted": {
            "type": "boolean",
            "title": "Processor Notice Accepted",
            "description": "Must be True. Owner acknowledges that AlterLab is a data processor under GDPR/CCPA and that the owner is responsible for lawful contact collection."
          },
          "auto_delete_days": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Delete Days",
            "description": "Auto-delete contacts older than this many days. None = no retention limit."
          }
        },
        "type": "object",
        "required": [
          "name",
          "processor_notice_accepted"
        ],
        "title": "ContactListCreate",
        "description": "Request to create a new contact list.\n\nThe caller MUST set processor_notice_accepted=True to acknowledge that\nAlterLab acts as a data processor under GDPR/CCPA for this list."
      },
      "ContactListItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "processor_notice_accepted": {
            "type": "boolean",
            "title": "Processor Notice Accepted"
          },
          "auto_delete_days": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Delete Days"
          },
          "contact_count": {
            "type": "integer",
            "title": "Contact Count",
            "description": "Number of contacts in the list",
            "default": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "processor_notice_accepted",
          "created_at",
          "updated_at"
        ],
        "title": "ContactListItem",
        "description": "Summary row for the list-of-lists endpoint."
      },
      "ContactListResponse": {
        "properties": {
          "lists": {
            "items": {
              "$ref": "#/components/schemas/ContactListItem"
            },
            "type": "array",
            "title": "Lists"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages"
          }
        },
        "type": "object",
        "required": [
          "lists",
          "total",
          "page",
          "limit",
          "total_pages"
        ],
        "title": "ContactListResponse",
        "description": "Paginated list of contact lists."
      },
      "ContactListUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "auto_delete_days": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Delete Days"
          }
        },
        "type": "object",
        "title": "ContactListUpdate",
        "description": "Request to update a contact list (partial)."
      },
      "ContactUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "company": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Company"
          },
          "custom_fields": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Fields"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Tags"
          },
          "consent_basis": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ConsentBasis"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "title": "ContactUpdate",
        "description": "Request to update a contact (partial)."
      },
      "ContentTruncationInfo": {
        "properties": {
          "truncated": {
            "type": "boolean",
            "title": "Truncated",
            "description": "Always True when this object is present."
          },
          "truncated_at_bytes": {
            "type": "integer",
            "title": "Truncated At Bytes",
            "description": "Number of bytes at which the content was cut before processing."
          },
          "original_size_bytes": {
            "type": "integer",
            "title": "Original Size Bytes",
            "description": "Original content size in bytes before truncation."
          },
          "truncation_reason": {
            "type": "string",
            "enum": [
              "readability_input_cap",
              "readability_output_cap",
              "response_body_cap"
            ],
            "title": "Truncation Reason",
            "description": "'readability_input_cap' — HTML exceeded 2 MB before Readability processing; 'readability_output_cap' — extracted text exceeded the output size cap; 'response_body_cap' — raw response body exceeded max_response_bytes limit."
          }
        },
        "type": "object",
        "required": [
          "truncated",
          "truncated_at_bytes",
          "original_size_bytes",
          "truncation_reason"
        ],
        "title": "ContentTruncationInfo",
        "description": "Truncation metadata present when a page exceeded size caps before extraction.\n\nOnly included in responses where content was truncated. Null for the vast\nmajority of pages that are within size limits."
      },
      "CostControls": {
        "properties": {
          "max_credits": {
            "anyOf": [
              {
                "type": "number",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits",
            "description": "Maximum credits to spend on this request"
          },
          "force_tier": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(1|2|3|3\\.5|4)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Force Tier",
            "description": "Force specific tier, skip escalation (1=curl, 2=http, 3=stealth, 3.5=lightjs, 4=browser)"
          },
          "max_tier": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(1|2|3|3\\.5|4)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Tier",
            "description": "Maximum tier to escalate to (1=curl, 2=http, 3=stealth, 3.5=lightjs, 4=browser)"
          },
          "prefer_cost": {
            "type": "boolean",
            "title": "Prefer Cost",
            "description": "Optimize for cost (try cheaper tiers first)",
            "default": false
          },
          "prefer_speed": {
            "type": "boolean",
            "title": "Prefer Speed",
            "description": "Optimize for speed (skip to reliable tier)",
            "default": false
          },
          "fail_fast": {
            "type": "boolean",
            "title": "Fail Fast",
            "description": "Return error instead of escalating to expensive tiers",
            "default": false
          },
          "time_budget": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 300.0,
                "minimum": 5.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Time Budget",
            "description": "Total wall-clock budget in seconds for the entire tier escalation sequence (5–300s). Escalation to the next tier is skipped if the remaining budget is insufficient for a meaningful attempt (T3 needs ≥5s, T4 needs ≥10s). When the budget is exhausted, the response includes time_budget_expired=true and the highest tier reached. Default: no limit."
          }
        },
        "type": "object",
        "title": "CostControls",
        "description": "Cost control parameters for scraping requests.\n\nTier levels:\n    1: curl - Direct HTTP, no fingerprinting ($0.0002)\n    2: http - curl_cffi with TLS fingerprinting ($0.0003)\n    3: stealth - curl_cffi with proxy ($0.002)\n    3.5: lightjs - T3 + JSON extraction without browser ($0.0025)\n    4: browser - Playwright full rendering ($0.004)"
      },
      "CostEstimate": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          },
          "estimated_tier": {
            "type": "string",
            "title": "Estimated Tier"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits"
          },
          "confidence": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high"
            ],
            "title": "Confidence"
          },
          "max_possible_credits": {
            "type": "integer",
            "title": "Max Possible Credits",
            "description": "Hard cost ceiling for this request — the credit cost if escalation reaches the most expensive tier (tier 4)."
          },
          "reasoning": {
            "type": "string",
            "title": "Reasoning",
            "description": "Human-readable explanation of why this tier was estimated, e.g. URL-pattern match or explicit force_tier override."
          }
        },
        "type": "object",
        "required": [
          "url",
          "estimated_tier",
          "estimated_credits",
          "confidence",
          "max_possible_credits",
          "reasoning"
        ],
        "title": "CostEstimate",
        "description": "Machine-readable pricing manifest for a scrape request (agent pre-flight budgeting)."
      },
      "CostProjectionResponse": {
        "properties": {
          "usage_trend": {
            "type": "string",
            "title": "Usage Trend"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "credits_allocated": {
            "type": "integer",
            "title": "Credits Allocated"
          }
        },
        "type": "object",
        "required": [
          "usage_trend",
          "credits_used",
          "credits_allocated"
        ],
        "title": "CostProjectionResponse",
        "description": "Projected costs for current billing period.\n\nNote: Cost values (base_cost, overage_cost, total_projected) are in dollars.\nCredit values are in credit units (1 credit = $0.001)."
      },
      "CrawlAdvancedOptions": {
        "properties": {
          "render_js": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "string",
                "const": "auto"
              }
            ],
            "title": "Render Js",
            "description": "Render JavaScript on crawled pages. true=always render (Tier 4), false=never render, 'auto'=smart detection per page (probes each URL, only renders JS-heavy pages with browser, saves 30-60% on mixed sites).",
            "default": false
          },
          "screenshot": {
            "type": "boolean",
            "title": "Screenshot",
            "description": "Capture screenshot of every crawled page",
            "default": false
          },
          "use_proxy": {
            "type": "boolean",
            "title": "Use Proxy",
            "description": "Route all crawl requests through premium proxy",
            "default": false
          },
          "wait_for": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wait For",
            "description": "CSS selector to wait for on each page"
          },
          "timeout": {
            "type": "integer",
            "maximum": 300.0,
            "minimum": 1.0,
            "title": "Timeout",
            "description": "Timeout per page in seconds",
            "default": 90
          },
          "delay": {
            "type": "number",
            "maximum": 30.0,
            "minimum": 0.0,
            "title": "Delay",
            "description": "Minimum seconds between requests to the same domain. Takes precedence over robots.txt Crawl-delay when higher. Range: 0-30 seconds.",
            "default": 0
          },
          "max_concurrency": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Max Concurrency",
            "description": "Maximum concurrent scrape jobs across all depth levels. Controls how many pages are being scraped simultaneously.",
            "default": 10
          },
          "depth_strategy": {
            "type": "string",
            "enum": [
              "eager",
              "sequential"
            ],
            "title": "Depth Strategy",
            "description": "Depth processing strategy. \"sequential\" (default) waits for all jobs at depth N to finish before starting depth N+1 — ensures deeper max_depth always discovers >= pages. \"eager\" starts next-depth jobs as soon as any current-depth job completes (faster but non-deterministic on cross-linked sites).",
            "default": "sequential"
          }
        },
        "type": "object",
        "title": "CrawlAdvancedOptions",
        "description": "Advanced options applied to every page scraped during the crawl."
      },
      "CrawlBilling": {
        "properties": {
          "credits_debited": {
            "type": "integer",
            "title": "Credits Debited",
            "description": "Total credits pre-debited (estimated cost at crawl start + depth expansions)"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Actual credits consumed by completed pages so far"
          },
          "credits_refunded": {
            "type": "integer",
            "title": "Credits Refunded",
            "description": "Credits refunded (cancellation or completion overpayment)",
            "default": 0
          },
          "estimated_cost_usd": {
            "type": "string",
            "title": "Estimated Cost Usd",
            "description": "Human-readable estimated cost, e.g. \"$0.06\""
          },
          "actual_cost_usd": {
            "type": "string",
            "title": "Actual Cost Usd",
            "description": "Human-readable actual cost so far, e.g. \"$0.04\""
          },
          "is_byop": {
            "type": "boolean",
            "title": "Is Byop",
            "description": "Whether BYOP (Bring Your Own Proxy) discount was applied",
            "default": false
          },
          "tier_breakdown": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Tier Breakdown",
            "description": "Pages completed per tier, e.g. {\"1\": 8, \"3\": 2, \"4\": 1}"
          },
          "smart_render_stats": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "integer"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Smart Render Stats",
            "description": "Smart render decision breakdown when render_js='auto'. e.g. {\"static\": 15, \"browser\": 5, \"unknown\": 1}"
          }
        },
        "type": "object",
        "required": [
          "credits_debited",
          "credits_used",
          "estimated_cost_usd",
          "actual_cost_usd"
        ],
        "title": "CrawlBilling",
        "description": "Aggregate billing summary for a crawl."
      },
      "CrawlBudgetStatus": {
        "properties": {
          "budget": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Budget",
            "description": "Configured budget limits per pattern, e.g. {\"/products/*\": 100, \"*\": 5}"
          },
          "counts": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Counts",
            "description": "Current page counts per pattern, e.g. {\"/products/*\": 42, \"*\": 3}"
          },
          "exhausted": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Exhausted",
            "description": "Patterns whose budget has been fully used"
          }
        },
        "type": "object",
        "required": [
          "budget",
          "counts"
        ],
        "title": "CrawlBudgetStatus",
        "description": "Per-pattern budget usage for a crawl with budget control."
      },
      "CrawlCancelResponse": {
        "properties": {
          "crawl_id": {
            "type": "string",
            "title": "Crawl Id"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Cancellation status. `cancelled` when the crawl was fully cancelled and the refund applied. `cancellation_pending` when a concurrent cancel request held the refund lock — the crawl is not yet in a terminal state; retry the cancel to receive the outstanding credits.",
            "default": "cancelled"
          },
          "cancelled_jobs": {
            "type": "integer",
            "title": "Cancelled Jobs",
            "description": "Number of pending jobs cancelled"
          },
          "credits_refunded": {
            "type": "integer",
            "title": "Credits Refunded",
            "description": "Credits refunded for unprocessed jobs"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits actually consumed before cancellation",
            "default": 0
          },
          "refund_pending": {
            "type": "boolean",
            "title": "Refund Pending",
            "description": "True when the refund could not be applied immediately because a concurrent cancel request holds the refund lock. Retry the cancel request to receive the outstanding credits.",
            "default": false
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Crawl cancelled. Unprocessed credits have been refunded."
          }
        },
        "type": "object",
        "required": [
          "crawl_id",
          "cancelled_jobs",
          "credits_refunded"
        ],
        "title": "CrawlCancelResponse",
        "description": "Response from DELETE /v1/crawl/{crawl_id}."
      },
      "CrawlCostControls": {
        "properties": {
          "max_credits": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits",
            "description": "Maximum total credits to spend on this crawl"
          },
          "max_tier": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(1|2|3|3\\.5|4)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Tier",
            "description": "Maximum tier to use for page scrapes"
          },
          "force_tier": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(1|2|3|3\\.5|4)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Force Tier",
            "description": "Force a specific tier for all pages"
          }
        },
        "type": "object",
        "title": "CrawlCostControls",
        "description": "Cost controls for the entire crawl."
      },
      "CrawlDepthStats": {
        "properties": {
          "depth": {
            "type": "integer",
            "title": "Depth",
            "description": "Depth level (0 = start URL)"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total pages at this depth"
          },
          "succeeded": {
            "type": "integer",
            "title": "Succeeded",
            "description": "Pages that scraped successfully",
            "default": 0
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "description": "Pages that failed",
            "default": 0
          },
          "pending": {
            "type": "integer",
            "title": "Pending",
            "description": "Pages still queued or processing",
            "default": 0
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Actual credits consumed at this depth (microcents)",
            "default": 0
          },
          "tier_breakdown": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Tier Breakdown",
            "description": "Pages per tier at this depth, e.g. {\"1\": 5, \"3\": 2}"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Urls",
            "description": "URLs discovered at this depth (truncated to first 200)"
          }
        },
        "type": "object",
        "required": [
          "depth",
          "total"
        ],
        "title": "CrawlDepthStats",
        "description": "Per-depth-level analytics for a crawl."
      },
      "CrawlHistoryItem": {
        "properties": {
          "crawl_id": {
            "type": "string",
            "title": "Crawl Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages",
            "default": 0
          },
          "completed_pages": {
            "type": "integer",
            "title": "Completed Pages",
            "default": 0
          },
          "failed_pages": {
            "type": "integer",
            "title": "Failed Pages",
            "default": 0
          },
          "credits_debited": {
            "type": "integer",
            "title": "Credits Debited",
            "default": 0
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "default": 0
          },
          "credits_refunded": {
            "type": "integer",
            "title": "Credits Refunded",
            "default": 0
          },
          "max_depth": {
            "type": "integer",
            "title": "Max Depth",
            "default": 0
          },
          "max_pages": {
            "type": "integer",
            "title": "Max Pages",
            "default": 50
          },
          "tier_breakdown": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Tier Breakdown"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "title": "Updated At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "duration_seconds": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration Seconds",
            "description": "Duration from creation to completion in seconds"
          }
        },
        "type": "object",
        "required": [
          "crawl_id",
          "url",
          "status",
          "created_at",
          "updated_at"
        ],
        "title": "CrawlHistoryItem",
        "description": "A single crawl record for the history list."
      },
      "CrawlListResponse": {
        "properties": {
          "crawls": {
            "items": {
              "$ref": "#/components/schemas/CrawlHistoryItem"
            },
            "type": "array",
            "title": "Crawls"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total matching crawls (for pagination)"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "offset": {
            "type": "integer",
            "title": "Offset"
          }
        },
        "type": "object",
        "required": [
          "crawls",
          "total",
          "limit",
          "offset"
        ],
        "title": "CrawlListResponse",
        "description": "Response from GET /v1/crawls."
      },
      "CrawlOutputStatus": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Connector type: s3, gcs, or webhook_stream"
          },
          "format": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Format",
            "description": "Output format (for cloud connectors)"
          },
          "pages_exported": {
            "type": "integer",
            "title": "Pages Exported",
            "description": "Number of pages successfully exported",
            "default": 0
          },
          "pages_failed": {
            "type": "integer",
            "title": "Pages Failed",
            "description": "Number of pages that failed to export",
            "default": 0
          },
          "bytes_uploaded": {
            "type": "integer",
            "title": "Bytes Uploaded",
            "description": "Total bytes uploaded (for cloud connectors)",
            "default": 0
          },
          "manifest_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Manifest Url",
            "description": "Manifest file key/path (set on completion)"
          }
        },
        "type": "object",
        "required": [
          "type"
        ],
        "title": "CrawlOutputStatus",
        "description": "Output connector status in crawl status response."
      },
      "CrawlPageResult": {
        "properties": {
          "job_id": {
            "type": "string",
            "title": "Job Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "priority_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Priority Score",
            "description": "URL priority score (0.0-1.0). Only present when priority config was used."
          },
          "result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "changes": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PageChanges"
              },
              {
                "type": "null"
              }
            ],
            "description": "Change detection result (only present when change_tracking is enabled)"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "url",
          "status"
        ],
        "title": "CrawlPageResult",
        "description": "Status and result of a single page within a crawl."
      },
      "CrawlPriority": {
        "properties": {
          "keywords": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Keywords",
            "description": "Keywords matched against URL path segments. e.g. [\"pricing\", \"api\", \"documentation\"]"
          },
          "boost_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Boost Patterns",
            "description": "Glob patterns — URLs matching any pattern receive a score boost. e.g. [\"/pricing*\", \"/docs/*\", \"/api/*\"]"
          },
          "demote_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Demote Patterns",
            "description": "Glob patterns — URLs matching any pattern receive a score reduction. e.g. [\"/blog/tag/*\", \"/author/*\", \"/page/*\"]"
          }
        },
        "type": "object",
        "title": "CrawlPriority",
        "description": "Content-aware URL prioritization — crawl high-value pages first.\n\nWhen configured, discovered URLs are scored (0.0-1.0) and enqueued in\npriority order (highest first).  When ``max_pages`` is reached the\nlowest-scoring URLs are the ones dropped."
      },
      "CrawlRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "Start URL for the crawl"
          },
          "max_pages": {
            "type": "integer",
            "maximum": 100000.0,
            "minimum": 1.0,
            "title": "Max Pages",
            "description": "Maximum number of pages to scrape (billing limits enforced separately)",
            "default": 50
          },
          "max_depth": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 0.0,
            "title": "Max Depth",
            "description": "Maximum link-following depth from start URL (0 = start page only)",
            "default": 3
          },
          "include_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Include Patterns",
            "description": "Glob patterns — only scrape URLs whose path matches at least one"
          },
          "exclude_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclude Patterns",
            "description": "Glob patterns — skip URLs whose path matches any"
          },
          "sitemap": {
            "type": "string",
            "enum": [
              "include",
              "skip",
              "only"
            ],
            "title": "Sitemap",
            "description": "Sitemap discovery mode. \"include\" (default): discover sitemap from robots.txt and parse it, also extract links. \"skip\": skip sitemap entirely, only discover via link extraction from start URL. \"only\": crawl exclusively from sitemap URLs — no link extraction, no depth crawling.",
            "default": "include"
          },
          "sitemap_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sitemap Path",
            "description": "Custom sitemap path to use instead of the default /sitemap.xml or robots.txt discovery. Must start with /. Example: /product-sitemap.xml, /sitemap_index.xml"
          },
          "budget": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "integer"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget",
            "description": "Per-path page budget — allocate max pages by URL path pattern. Keys are glob patterns matched against the URL path, values are page limits. Use \"*\" as the catch-all default. Most-specific pattern wins (longest match). Global max_pages is still enforced as the hard cap. Example: {\"/products/*\": 100, \"/blog/*\": 50, \"*\": 5}"
          },
          "priority": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlPriority"
              },
              {
                "type": "null"
              }
            ],
            "description": "Content-aware URL prioritization. When set, discovered URLs are scored by keyword relevance, pattern matching, and depth — high-value pages are scraped first."
          },
          "max_concurrency": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 1.0,
            "title": "Max Concurrency",
            "description": "Maximum concurrent pages to scrape simultaneously per domain. The crawler auto-throttles below this limit when servers return 429/503 errors, and speeds up when responses are fast.",
            "default": 10
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Custom HTTP headers injected into every page request during the crawl. Useful for auth tokens (Authorization: Bearer …), cookies, or custom User-Agent. Domain playbook headers take precedence over these."
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown",
                    "rag",
                    "content"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats for each scraped page"
          },
          "extraction": {
            "anyOf": [
              {
                "type": "string",
                "const": "auto"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction",
            "description": "Set to \"auto\" for Cortex-powered auto-extraction. Cortex detects page type (article, product, listing, etc.) and applies domain-learned extraction playbooks. Returns structured data without a user-defined schema. Mutually exclusive with extraction_schema."
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON schema for structured extraction on each page"
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Pre-defined extraction profile for each page"
          },
          "extraction_template": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Template",
            "description": "Shorthand for extraction_profile. Selects a pre-built schema template by name. Mutually exclusive with extraction_profile."
          },
          "extraction_provider": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "openai",
                  "anthropic",
                  "openrouter",
                  "groq"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Provider",
            "description": "LLM provider to use for extraction on each crawled page. Selects the matching BYOK key registered at /dashboard/settings/llm-keys. When omitted, the most recently used registered key is used automatically."
          },
          "extraction_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Model",
            "description": "Override model ID for extraction (e.g. 'gpt-4o', 'llama3-70b-8192'). Applied to every page in the crawl. When omitted, the model saved on the registered BYOK key is used."
          },
          "respect_robots": {
            "type": "boolean",
            "title": "Respect Robots",
            "description": "Respect robots.txt rules for the target domain",
            "default": true
          },
          "include_subdomains": {
            "type": "boolean",
            "title": "Include Subdomains",
            "description": "Include links to subdomains during discovery",
            "default": false
          },
          "change_tracking": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChangeTrackingConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Enable change detection to compare this crawl against the previous run with the same tracking_id. Detects new, changed, unchanged, and removed pages."
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL to notify on crawl completion. Fires a single POST with crawl summary when the crawl finishes. Legacy field — prefer `webhook` for full event filtering, HMAC signing, and metadata."
          },
          "webhook": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlWebhookConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Structured webhook configuration for real-time crawl event delivery. Supports per-event filtering, HMAC-SHA256 signing, custom headers, and metadata. Takes precedence over `webhook_url` when both are provided."
          },
          "advanced": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlAdvancedOptions"
              },
              {
                "type": "null"
              }
            ],
            "description": "Advanced scraping options applied to every page"
          },
          "cost_controls": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlCostControls"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cost controls for the entire crawl"
          },
          "output": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/S3OutputConfig"
              },
              {
                "$ref": "#/components/schemas/GCSOutputConfig"
              },
              {
                "$ref": "#/components/schemas/WebhookStreamOutputConfig"
              },
              {
                "type": "null"
              }
            ],
            "title": "Output",
            "description": "Output connector for delivering crawl results directly to cloud storage or a streaming webhook. When set, results are delivered as each page completes rather than held exclusively in Redis. Redis polling still works when output is configured. Supported types: \"s3\", \"gcs\", \"webhook_stream\"."
          },
          "storage": {
            "type": "string",
            "enum": [
              "redis",
              "s3",
              "r2"
            ],
            "title": "Storage",
            "description": "Storage backend for crawl results. \"redis\" (default): results stored in Redis with 2h TTL, returned inline. \"s3\" or \"r2\": results uploaded to S3/R2 as JSONL on completion, status endpoint returns a presigned download URL. Cloud storage provides 30-day retention and handles large crawls (10k+ pages).",
            "default": "redis"
          },
          "cache": {
            "type": "boolean",
            "title": "Cache",
            "description": "Enable caching. When True, per-URL results may be returned from cache if available.",
            "default": false
          },
          "cache_ttl": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 86400.0,
                "minimum": 60.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Cache Ttl",
            "description": "Cache TTL in seconds (60-86400). Defaults to 3600 (60 min) when cache=True."
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "description": "Force fresh fetch even if cache=True. Invalidates existing cache entries.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "CrawlRequest",
        "description": "Request body for POST /v1/crawl."
      },
      "CrawlResponse": {
        "properties": {
          "crawl_id": {
            "type": "string",
            "title": "Crawl Id"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "default": "scraping"
          },
          "estimated_pages": {
            "type": "integer",
            "title": "Estimated Pages",
            "description": "Number of pages discovered for scraping"
          },
          "total_enqueued": {
            "type": "integer",
            "title": "Total Enqueued",
            "description": "Number of scrape jobs actually enqueued"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits",
            "description": "Total credits pre-debited"
          },
          "effective_max_concurrency": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Effective Max Concurrency",
            "description": "Actual max concurrency applied to this crawl (may be lower than requested if the user's plan tier caps it)"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Crawl started. Poll GET /v1/crawl/{crawl_id} for progress."
          },
          "crawl_slot_limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Crawl Slot Limit",
            "description": "Maximum concurrent crawl sessions allowed for your balance tier"
          },
          "crawl_slot_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Crawl Slot Tier",
            "description": "Slug identifier for the balance tier used to determine crawl slot limit. Always one of: 'free', 'basic', 'growth', 'scale', 'high_volume'. Use this for programmatic tier comparisons."
          },
          "storage": {
            "type": "string",
            "title": "Storage",
            "description": "Effective storage backend for this crawl. \"redis\" = inline results, \"s3\"/\"r2\" = presigned download URL on completion. May differ from the requested storage if auto-upgraded or if cloud storage was unavailable.",
            "default": "redis"
          }
        },
        "type": "object",
        "required": [
          "crawl_id",
          "estimated_pages",
          "total_enqueued",
          "estimated_credits"
        ],
        "title": "CrawlResponse",
        "description": "Response from POST /v1/crawl (202 Accepted)."
      },
      "CrawlResumeRequest": {
        "properties": {
          "retry_failed": {
            "type": "boolean",
            "title": "Retry Failed",
            "description": "Retry jobs that ended in 'failed' status",
            "default": true
          },
          "retry_statuses": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "failed",
                    "cancelled"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Retry Statuses",
            "description": "Job statuses to retry. Defaults to ['failed'] when retry_failed=True. Use ['failed', 'cancelled'] to also retry cancelled jobs."
          },
          "additional_urls": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "maxLength": 2083,
                  "minLength": 1,
                  "format": "uri"
                },
                "type": "array",
                "maxItems": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Additional Urls",
            "description": "Extra URLs to add to the crawl (SSRF-validated and deduped)"
          }
        },
        "type": "object",
        "title": "CrawlResumeRequest",
        "description": "Request body for POST /v1/crawl/{crawl_id}/resume."
      },
      "CrawlResumeResponse": {
        "properties": {
          "crawl_id": {
            "type": "string",
            "title": "Crawl Id"
          },
          "resumed": {
            "type": "boolean",
            "title": "Resumed",
            "default": true
          },
          "retried_jobs": {
            "type": "integer",
            "title": "Retried Jobs",
            "description": "Number of previously-failed/cancelled jobs re-enqueued"
          },
          "additional_urls_queued": {
            "type": "integer",
            "title": "Additional Urls Queued",
            "description": "Number of additional URLs accepted and enqueued",
            "default": 0
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits",
            "description": "Credits debited for resumed jobs"
          },
          "resume_count": {
            "type": "integer",
            "title": "Resume Count",
            "description": "How many times this crawl has been resumed"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Crawl resumed."
          }
        },
        "type": "object",
        "required": [
          "crawl_id",
          "retried_jobs",
          "estimated_credits",
          "resume_count"
        ],
        "title": "CrawlResumeResponse",
        "description": "Response from POST /v1/crawl/{crawl_id}/resume."
      },
      "CrawlScheduleCrawlConfig": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "Start URL for the crawl"
          },
          "max_pages": {
            "type": "integer",
            "maximum": 10000.0,
            "minimum": 1.0,
            "title": "Max Pages",
            "default": 50
          },
          "max_depth": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 0.0,
            "title": "Max Depth",
            "default": 3
          },
          "include_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Include Patterns"
          },
          "exclude_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclude Patterns"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema"
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile"
          },
          "respect_robots": {
            "type": "boolean",
            "title": "Respect Robots",
            "default": true
          },
          "include_subdomains": {
            "type": "boolean",
            "title": "Include Subdomains",
            "default": false
          },
          "render_js": {
            "type": "boolean",
            "title": "Render Js",
            "default": false
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "change_tracking": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChangeTrackingConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Enable cross-run change detection. When set, each run compares page content hashes against the previous run and stores a change summary (new/changed/unchanged/removed counts). Uses the schedule ID as the tracking_id by default for consistent history across runs."
          },
          "sitemap": {
            "type": "string",
            "enum": [
              "include",
              "skip",
              "only"
            ],
            "title": "Sitemap",
            "description": "\"include\" (default): discover sitemap from robots.txt and parse it, also extract links. \"skip\": skip sitemap entirely, only discover via link extraction from start URL. \"only\": crawl exclusively from sitemap URLs — no link extraction, no depth crawling.",
            "default": "include"
          },
          "sitemap_path": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sitemap Path",
            "description": "Custom sitemap path to use instead of the default /sitemap.xml or robots.txt discovery. Must start with /. Example: /product-sitemap.xml"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "CrawlScheduleCrawlConfig",
        "description": "Frozen crawl configuration executed on each scheduled run.\n\nMirrors the essential fields of CrawlRequest but stored as a JSON blob\nso the schedule is self-contained (no user input at execution time)."
      },
      "CrawlScheduleCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron",
            "description": "Cron expression (5 fields), e.g. '0 6 * * *'"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "crawl_config": {
            "$ref": "#/components/schemas/CrawlScheduleCrawlConfig"
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs",
            "description": "Maximum number of runs before the schedule auto-disables"
          },
          "max_credits_per_run": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits Per Run",
            "description": "Credit cap per run (microcents). Crawl is trimmed if estimate exceeds this."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name",
          "cron",
          "crawl_config"
        ],
        "title": "CrawlScheduleCreateRequest",
        "description": "Create a new crawl schedule."
      },
      "CrawlScheduleListResponse": {
        "properties": {
          "schedules": {
            "items": {
              "$ref": "#/components/schemas/CrawlScheduleResponse"
            },
            "type": "array",
            "title": "Schedules"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "schedules",
          "total"
        ],
        "title": "CrawlScheduleListResponse",
        "description": "Paginated list of crawl schedules."
      },
      "CrawlScheduleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "crawl_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Crawl Config"
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs"
          },
          "max_credits_per_run": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits Per Run"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "next_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Run At"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "cron",
          "timezone",
          "crawl_config",
          "is_active",
          "run_count",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "CrawlScheduleResponse",
        "description": "Crawl schedule detail response."
      },
      "CrawlScheduleRunListResponse": {
        "properties": {
          "runs": {
            "items": {
              "$ref": "#/components/schemas/CrawlScheduleRunResponse"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "runs",
          "total"
        ],
        "title": "CrawlScheduleRunListResponse",
        "description": "Paginated list of crawl schedule runs."
      },
      "CrawlScheduleRunResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "crawl_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Crawl Id"
          },
          "pages_total": {
            "type": "integer",
            "title": "Pages Total"
          },
          "pages_completed": {
            "type": "integer",
            "title": "Pages Completed"
          },
          "pages_failed": {
            "type": "integer",
            "title": "Pages Failed"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "change_summary": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Change Summary",
            "description": "Change detection summary for this run. Present when change_tracking is enabled in crawl_config. Contains new_pages, changed_pages, unchanged_pages, removed_pages counts."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "status",
          "pages_total",
          "pages_completed",
          "pages_failed",
          "credits_used",
          "created_at"
        ],
        "title": "CrawlScheduleRunResponse",
        "description": "Execution record for a scheduled crawl run."
      },
      "CrawlScheduleUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "cron": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "crawl_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlScheduleCrawlConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs"
          },
          "max_credits_per_run": {
            "anyOf": [
              {
                "type": "integer",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits Per Run"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          }
        },
        "type": "object",
        "title": "CrawlScheduleUpdateRequest",
        "description": "Update an existing crawl schedule."
      },
      "CrawlStatusResponse": {
        "properties": {
          "crawl_id": {
            "type": "string",
            "title": "Crawl Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "completed": {
            "type": "integer",
            "title": "Completed"
          },
          "failed": {
            "type": "integer",
            "title": "Failed"
          },
          "in_progress": {
            "type": "integer",
            "title": "In Progress"
          },
          "credits_debited": {
            "type": "integer",
            "title": "Credits Debited"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "current_depth": {
            "type": "integer",
            "title": "Current Depth",
            "description": "Current crawl depth being processed",
            "default": 0
          },
          "max_depth": {
            "type": "integer",
            "title": "Max Depth",
            "description": "Maximum crawl depth configured",
            "default": 0
          },
          "active_depths": {
            "items": {
              "type": "integer"
            },
            "type": "array",
            "title": "Active Depths",
            "description": "Depth levels that currently have pending or in-progress jobs"
          },
          "total_discovered": {
            "type": "integer",
            "title": "Total Discovered",
            "description": "Total unique URLs discovered across all depths",
            "default": 0
          },
          "effective_crawl_delay": {
            "type": "number",
            "title": "Effective Crawl Delay",
            "description": "Effective inter-request delay in seconds. Computed as max(user_delay, min(robots_crawl_delay, 10)).",
            "default": 0
          },
          "billing": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlBilling"
              },
              {
                "type": "null"
              }
            ],
            "description": "Aggregate billing summary with tier breakdown and refund details"
          },
          "change_summary": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ChangeSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "Crawl-level change summary (only present when change_tracking is enabled and the crawl is completed/partial)"
          },
          "budget_status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlBudgetStatus"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-path budget usage. Only present when budget was configured."
          },
          "output_status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CrawlOutputStatus"
              },
              {
                "type": "null"
              }
            ],
            "description": "Output connector status. Only present when output was configured."
          },
          "pagination": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PaginationMeta"
              },
              {
                "type": "null"
              }
            ],
            "description": "Pagination metadata. Present when pages are included."
          },
          "pages": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/CrawlPageResult"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pages",
            "description": "Per-page results. Paginated when limit/offset are provided."
          },
          "depth_stats": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/CrawlDepthStats"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth Stats",
            "description": "Per-depth analytics. Only included when include_depth_stats=true."
          },
          "storage_backend": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "s3",
                  "r2"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Storage Backend",
            "description": "Storage backend used for this crawl's results. Only present when storage is \"s3\" or \"r2\". When set, use results_url to download results as JSONL."
          },
          "results_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Results Url",
            "description": "Presigned download URL for crawl results (JSONL format). Only present when storage_backend is \"s3\" or \"r2\" and crawl is completed or partial. URL expires after 30 days (configurable)."
          },
          "results_expiry": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Results Expiry",
            "description": "ISO 8601 timestamp when the results_url expires. Only present when results_url is set."
          }
        },
        "type": "object",
        "required": [
          "crawl_id",
          "status",
          "total",
          "completed",
          "failed",
          "in_progress",
          "credits_debited",
          "created_at"
        ],
        "title": "CrawlStatusResponse",
        "description": "Response from GET /v1/crawl/{crawl_id}."
      },
      "CrawlWebhookConfig": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "URL to receive webhook events"
          },
          "events": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Events",
            "description": "Event types to subscribe to. Default: all events. Options: crawl.started, crawl.page.completed, crawl.page.failed, crawl.completed, crawl.failed"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256,
                "minLength": 8
              },
              {
                "type": "null"
              }
            ],
            "title": "Secret",
            "description": "Shared secret for HMAC-SHA256 signing. When set, each delivery includes X-Webhook-Signature and X-Webhook-Timestamp headers."
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Custom HTTP headers to include with every webhook delivery"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Custom JSON metadata passed through in every event payload"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "CrawlWebhookConfig",
        "description": "Webhook configuration for crawl event notifications.\n\nWhen provided, the crawl will deliver real-time events to the specified URL.\nSupports per-event filtering, HMAC-SHA256 signing, custom headers, and\nmetadata passthrough."
      },
      "CreatePlanRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "Plan display name shown to potential subscribers"
          },
          "monthly_price_cents": {
            "type": "integer",
            "minimum": 100.0,
            "title": "Monthly Price Cents",
            "description": "Monthly price in USD cents (minimum $1.00 = 100 cents)"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Optional description shown on the subscription page"
          }
        },
        "type": "object",
        "required": [
          "name",
          "monthly_price_cents"
        ],
        "title": "CreatePlanRequest",
        "description": "POST /creator/subscription-plans request body."
      },
      "CreatorAnalyticsResponse": {
        "properties": {
          "arr_cents": {
            "type": "integer",
            "title": "Arr Cents"
          },
          "mrr_cents": {
            "type": "integer",
            "title": "Mrr Cents"
          },
          "subscriber_count": {
            "type": "integer",
            "title": "Subscriber Count"
          },
          "churn_rate_pct": {
            "type": "number",
            "title": "Churn Rate Pct"
          },
          "ltv_cents": {
            "type": "integer",
            "title": "Ltv Cents"
          },
          "mrr_trend": {
            "items": {
              "$ref": "#/components/schemas/MrrTrendPoint"
            },
            "type": "array",
            "title": "Mrr Trend"
          },
          "subscriber_trend": {
            "items": {
              "$ref": "#/components/schemas/SubscriberTrendPoint"
            },
            "type": "array",
            "title": "Subscriber Trend"
          },
          "revenue_by_plan": {
            "items": {
              "$ref": "#/components/schemas/RevenuePlanItem"
            },
            "type": "array",
            "title": "Revenue By Plan"
          },
          "payout_history": {
            "items": {
              "$ref": "#/components/schemas/PayoutHistoryItem"
            },
            "type": "array",
            "title": "Payout History"
          }
        },
        "type": "object",
        "required": [
          "arr_cents",
          "mrr_cents",
          "subscriber_count",
          "churn_rate_pct",
          "ltv_cents",
          "mrr_trend",
          "subscriber_trend",
          "revenue_by_plan",
          "payout_history"
        ],
        "title": "CreatorAnalyticsResponse",
        "description": "GET /creator/analytics response."
      },
      "CredentialField": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "label": {
            "type": "string",
            "title": "Label"
          },
          "type": {
            "type": "string",
            "title": "Type",
            "default": "text"
          },
          "required": {
            "type": "boolean",
            "title": "Required",
            "default": true
          },
          "placeholder": {
            "type": "string",
            "title": "Placeholder",
            "default": ""
          },
          "help_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Help Text"
          }
        },
        "type": "object",
        "required": [
          "name",
          "label"
        ],
        "title": "CredentialField",
        "description": "Definition of a credential field for provider setup."
      },
      "CreditForecast": {
        "properties": {
          "daily": {
            "type": "number",
            "title": "Daily"
          },
          "weekly": {
            "type": "number",
            "title": "Weekly"
          },
          "monthly": {
            "type": "number",
            "title": "Monthly"
          },
          "balance_microcents": {
            "type": "integer",
            "title": "Balance Microcents"
          },
          "days_remaining": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Days Remaining"
          }
        },
        "type": "object",
        "required": [
          "daily",
          "weekly",
          "monthly",
          "balance_microcents"
        ],
        "title": "CreditForecast",
        "description": "Projected credit consumption based on active schedules."
      },
      "CreditTransactionItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "type": {
            "type": "string",
            "title": "Type"
          },
          "amount": {
            "type": "integer",
            "title": "Amount"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "reference_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reference Type"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "crawl_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Crawl Id"
          },
          "domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain"
          },
          "page_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Page Count"
          }
        },
        "type": "object",
        "required": [
          "id",
          "type",
          "amount",
          "description",
          "created_at"
        ],
        "title": "CreditTransactionItem",
        "description": "A credit_ledger transaction for display in transaction history."
      },
      "CreditTransactionsResponse": {
        "properties": {
          "transactions": {
            "items": {
              "$ref": "#/components/schemas/CreditTransactionItem"
            },
            "type": "array",
            "title": "Transactions"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More"
          }
        },
        "type": "object",
        "required": [
          "transactions",
          "total",
          "has_more"
        ],
        "title": "CreditTransactionsResponse",
        "description": "Credit ledger transactions (debits, refunds)."
      },
      "CsvImportResult": {
        "properties": {
          "list_id": {
            "type": "string",
            "format": "uuid",
            "title": "List Id",
            "description": "Contact list that was imported into"
          },
          "imported": {
            "type": "integer",
            "title": "Imported",
            "description": "Number of new contacts successfully inserted"
          },
          "skipped": {
            "type": "integer",
            "title": "Skipped",
            "description": "Number of rows skipped due to duplicate email"
          },
          "errors": {
            "type": "integer",
            "title": "Errors",
            "description": "Number of rows that failed validation and were skipped"
          },
          "error_samples": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Error Samples",
            "description": "Up to 10 sample error messages (row index + reason)"
          },
          "truncated": {
            "type": "boolean",
            "title": "Truncated",
            "description": "True when the CSV file contained more rows than the per-request limit. Only the first rows_in_file data rows were processed.",
            "default": false
          },
          "rows_in_file": {
            "type": "integer",
            "title": "Rows In File",
            "description": "Total data rows attempted (excluding the header). Equals imported + skipped + errors when truncated is False.",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "list_id",
          "imported",
          "skipped",
          "errors"
        ],
        "title": "CsvImportResult",
        "description": "Result of a CSV import into a contact list.\n\nRows that contain an email already present in the list are silently\nskipped (dedup by lower(email)) — they are counted in ``skipped``.\nRows that fail validation (missing email, malformed value) are counted\nin ``errors`` along with a sample of error messages.\n\nWhen the file contains more rows than the per-request limit\n(``_CSV_IMPORT_ROW_LIMIT``), processing stops after the limit and\n``truncated`` is set to ``True``.  ``rows_in_file`` reflects the\nnumber of data rows actually attempted — callers should prompt the\nuser to split the file and re-upload the remainder."
      },
      "DailyRunBucket": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date",
            "description": "ISO date string (YYYY-MM-DD)"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "default": 0
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "default": 0
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "default": 0
          },
          "cancelled": {
            "type": "integer",
            "title": "Cancelled",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "date"
        ],
        "title": "DailyRunBucket",
        "description": "Aggregated run counts for a single calendar day."
      },
      "DashboardBootstrapBalance": {
        "properties": {
          "balance_microcents": {
            "type": "integer",
            "title": "Balance Microcents"
          },
          "balance_display": {
            "type": "string",
            "title": "Balance Display"
          },
          "tier_slug": {
            "type": "string",
            "title": "Tier Slug"
          }
        },
        "type": "object",
        "required": [
          "balance_microcents",
          "balance_display",
          "tier_slug"
        ],
        "title": "DashboardBootstrapBalance",
        "description": "Balance summary fields returned by the dashboard bootstrap endpoint."
      },
      "DashboardBootstrapResponse": {
        "properties": {
          "user": {
            "$ref": "#/components/schemas/DashboardBootstrapUser"
          },
          "balance": {
            "$ref": "#/components/schemas/DashboardBootstrapBalance"
          },
          "has_api_keys": {
            "type": "boolean",
            "title": "Has Api Keys"
          }
        },
        "type": "object",
        "required": [
          "user",
          "balance",
          "has_api_keys"
        ],
        "title": "DashboardBootstrapResponse",
        "description": "Single bootstrap response combining user profile + balance + key presence.\n\nReturned by GET /api/v1/dashboard/bootstrap.  The frontend calls this\nsingle endpoint on mount instead of the former two sequential calls\n(GET /auth/profile + GET /billing/balance)."
      },
      "DashboardBootstrapUser": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "subscription_tier": {
            "type": "string",
            "title": "Subscription Tier",
            "default": "free"
          },
          "credits_remaining": {
            "type": "integer",
            "title": "Credits Remaining",
            "default": 0
          },
          "credits_total": {
            "type": "integer",
            "title": "Credits Total",
            "default": 0
          },
          "welcome_shown": {
            "type": "boolean",
            "title": "Welcome Shown",
            "default": false
          },
          "reduced_bonus": {
            "type": "boolean",
            "title": "Reduced Bonus",
            "default": false
          },
          "beta_features": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Beta Features",
            "default": []
          },
          "org_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Id"
          },
          "account_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Account Type"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email"
        ],
        "title": "DashboardBootstrapUser",
        "description": "User profile fields returned by the dashboard bootstrap endpoint."
      },
      "DashboardStatsResponse": {
        "properties": {
          "credits_available": {
            "type": "integer",
            "title": "Credits Available"
          },
          "credits_change_percent": {
            "type": "number",
            "title": "Credits Change Percent"
          },
          "total_requests_month": {
            "type": "integer",
            "title": "Total Requests Month"
          },
          "requests_change_percent": {
            "type": "number",
            "title": "Requests Change Percent"
          },
          "cache_hit_rate": {
            "type": "number",
            "title": "Cache Hit Rate"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          },
          "balance_display": {
            "type": "string",
            "title": "Balance Display",
            "default": "$0.00"
          },
          "extraction_count_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Count Month"
          },
          "extraction_spend_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Spend Month"
          }
        },
        "type": "object",
        "required": [
          "credits_available",
          "credits_change_percent",
          "total_requests_month",
          "requests_change_percent",
          "cache_hit_rate"
        ],
        "title": "DashboardStatsResponse",
        "description": "Dashboard stats response."
      },
      "DeactivateSessionResponse": {
        "properties": {
          "deactivated": {
            "type": "boolean",
            "title": "Deactivated"
          },
          "propagated": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Propagated"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "type": "object",
        "required": [
          "deactivated"
        ],
        "title": "DeactivateSessionResponse",
        "description": "Response for per-session deactivation."
      },
      "DecryptedKeyResponse": {
        "properties": {
          "key": {
            "type": "string",
            "title": "Key"
          }
        },
        "type": "object",
        "required": [
          "key"
        ],
        "title": "DecryptedKeyResponse",
        "description": "Response for decrypted API key value."
      },
      "DefaultOrganizationResponse": {
        "properties": {
          "default_organization": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/OrganizationWithRole"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "title": "DefaultOrganizationResponse",
        "description": "Response with user's default organization."
      },
      "DeleteAccountRequest": {
        "properties": {
          "password": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Password"
          },
          "confirm": {
            "type": "boolean",
            "title": "Confirm",
            "default": false
          }
        },
        "type": "object",
        "title": "DeleteAccountRequest",
        "description": "Delete account request."
      },
      "DeliveryHistoryItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id",
            "description": "Delivery receipt UUID."
          },
          "bulk_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bulk Id",
            "description": "Bulk submission ID if this delivery was part of a bulk job batch. Null for manually-triggered deliveries."
          },
          "config_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config Id",
            "description": "Delivery config UUID used for this delivery. Null if the config was subsequently deleted."
          },
          "delivery_type": {
            "type": "string",
            "title": "Delivery Type",
            "description": "Delivery method type: 's3' | 'webhook' | 'polling' | 'batch_export'."
          },
          "method": {
            "type": "string",
            "title": "Method",
            "description": "Resolved delivery method identifier."
          },
          "destination": {
            "type": "string",
            "title": "Destination",
            "description": "Sanitized delivery destination. S3: 'bucket/prefix'. Webhook: endpoint URL. No credentials."
          },
          "bytes_written": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Bytes Written",
            "description": "Bytes written to the destination (0 for polling)."
          },
          "result_count": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Result Count",
            "description": "Number of result items delivered."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Delivery outcome: 'success' | 'failure'."
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message",
            "description": "Error description on failure. Null on success."
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "title": "Delivered At",
            "description": "UTC timestamp when delivery completed or failed."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "UTC timestamp when this receipt was persisted."
          }
        },
        "type": "object",
        "required": [
          "id",
          "delivery_type",
          "method",
          "destination",
          "bytes_written",
          "result_count",
          "status",
          "delivered_at",
          "created_at"
        ],
        "title": "DeliveryHistoryItem",
        "description": "A single delivery receipt in the delivery history list.\n\n``destination`` is sanitized — S3: bucket/prefix only, webhook: endpoint\nURL only. Credentials and signing secrets are NEVER returned."
      },
      "DeliveryHistoryResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/DeliveryHistoryItem"
            },
            "type": "array",
            "title": "Items",
            "description": "Delivery receipts, newest first."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total receipts matching the query (for pagination)."
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Page size used in this response."
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Offset used in this response."
          },
          "filters": {
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ]
            },
            "type": "object",
            "title": "Filters",
            "description": "Active filters echoed back. Keys: 'status', 'delivery_type'. Null value means the filter was not applied."
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset"
        ],
        "title": "DeliveryHistoryResponse",
        "description": "Paginated response for GET /api/v1/b2b/deliveries."
      },
      "DeliveryType": {
        "type": "string",
        "enum": [
          "s3",
          "webhook",
          "polling",
          "batch_export"
        ],
        "title": "DeliveryType",
        "description": "Supported delivery methods for tenant data output."
      },
      "DemographicProfileBuildRequest": {
        "properties": {
          "age_bucket": {
            "type": "string",
            "enum": [
              "18-24",
              "25-34",
              "35-44",
              "45-54"
            ],
            "title": "Age Bucket",
            "description": "Target age range for the demographic profile.  Google must infer this age group from cookie-based activity signals."
          },
          "gender": {
            "type": "string",
            "enum": [
              "F",
              "M"
            ],
            "title": "Gender",
            "description": "Target gender for the demographic profile — 'F' (Female) or 'M' (Male).  Case-insensitive on input; stored as uppercase."
          },
          "geo": {
            "type": "string",
            "maxLength": 2,
            "minLength": 2,
            "pattern": "^[A-Z]{2}$",
            "title": "Geo",
            "description": "ISO 3166-1 alpha-2 country code for the geo target (e.g. 'US', 'GB').  Determines which consent cookies (SOCS) are injected before YouTube visits.  Must be uppercase.",
            "default": "US"
          },
          "video_count": {
            "type": "integer",
            "maximum": 25.0,
            "minimum": 1.0,
            "title": "Video Count",
            "description": "Number of YouTube videos to watch during warmup (1–25).  The investigation recommends 10-15 videos for a stable signal; 12 is the default midpoint.",
            "default": 12
          },
          "profile_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "minLength": 1,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Id",
            "description": "Demographic profile identifier.  Must contain only alphanumerics, underscores, hyphens, and dots.  Max 64 characters."
          },
          "proxy_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Url",
            "description": "Optional proxy URL for the YouTube warmup browser (``scheme://[user:pass@]host:port``).  ISP or residential proxies are strongly preferred — datacenter IPs are a bot signal for YouTube and prevent ``VISITOR_INFO1_LIVE``/``NID`` cookies from being set.  When omitted the worker runs the warmup without a proxy, which may produce a profile with no demographic cookies on datacenter IPs."
          }
        },
        "type": "object",
        "required": [
          "age_bucket",
          "gender"
        ],
        "title": "DemographicProfileBuildRequest",
        "description": "Request body for POST /api/v1/b2b/profiles.\n\nTriggers an asynchronous YouTube demographic warmup session to build a\nbrowser profile with a specific age/gender demographic signal.  The\nprofile is identified by the returned ``profile_id``, which can then be\npassed as ``session_pool_id`` in subsequent SERP search requests to route\nthose searches through the demographically-targeted browser session.\n\nWarmup takes ~15-18 minutes.  Poll GET /api/v1/b2b/profiles/{profile_id}\nuntil ``status == \"complete\"`` before submitting SERP jobs."
      },
      "DemographicProfileBuildResponse": {
        "properties": {
          "profile_id": {
            "type": "string",
            "title": "Profile Id",
            "description": "Unique identifier for this profile build.  Pass as ``session_pool_id`` in SERP search requests once status == 'complete'."
          },
          "status": {
            "type": "string",
            "enum": [
              "building",
              "complete",
              "failed"
            ],
            "title": "Status",
            "description": "'building' — warmup in progress (~15-18 min); 'complete' — profile ready, cookie_jar available; 'failed' — warmup failed (see error field)."
          },
          "age_bucket": {
            "type": "string",
            "title": "Age Bucket",
            "description": "Target age range requested."
          },
          "gender": {
            "type": "string",
            "title": "Gender",
            "description": "Target gender requested ('F' or 'M')."
          },
          "geo": {
            "type": "string",
            "title": "Geo",
            "description": "Target geo code (ISO 3166-1 alpha-2)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the build task was enqueued."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable status message.",
            "default": "Profile warmup started.  Poll GET /api/v1/b2b/profiles/{profile_id} until status == 'complete'.  Warmup takes ~15-18 minutes."
          }
        },
        "type": "object",
        "required": [
          "profile_id",
          "status",
          "age_bucket",
          "gender",
          "geo",
          "created_at"
        ],
        "title": "DemographicProfileBuildResponse",
        "description": "Response body for POST /api/v1/b2b/profiles (202 Accepted)."
      },
      "DemographicProfileListItem": {
        "properties": {
          "profile_id": {
            "type": "string",
            "title": "Profile Id",
            "description": "Profile identifier."
          },
          "status": {
            "type": "string",
            "enum": [
              "building",
              "complete",
              "failed"
            ],
            "title": "Status",
            "description": "'building' — warmup still in progress; 'complete' — demographic profile ready; 'failed' — warmup failed."
          },
          "age_bucket": {
            "type": "string",
            "title": "Age Bucket",
            "description": "Target age range requested."
          },
          "gender": {
            "type": "string",
            "title": "Gender",
            "description": "Target gender requested ('F' or 'M')."
          },
          "geo": {
            "type": "string",
            "title": "Geo",
            "description": "Target geo code (ISO 3166-1 alpha-2)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the build task was enqueued."
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At",
            "description": "When the build state was last updated (None if still building)."
          },
          "inferred_age_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inferred Age Bucket",
            "description": "Age bucket inferred by Google for this profile.  Only present when status == 'complete'."
          },
          "inferred_gender": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inferred Gender",
            "description": "Gender inferred by Google ('Male'/'Female').  Only present when status == 'complete'."
          },
          "is_inferred": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Inferred",
            "description": "True when Google has registered at least one demographic attribute.  False when adssettings showed no inference."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message when status == 'failed'.  None otherwise."
          },
          "demographic_ad_rate": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Demographic Ad Rate",
            "description": "demographic_ads / total_ads as a 0.0-1.0 fraction, aggregated over this profile's most recent completed jobs (bounded window — see list_demographic_profiles).  Only computed for status == 'complete' profiles.  None when the profile has no completed jobs yet, or when status != 'complete'.  For the exact figure over a profile's full job history, use GET /profiles/{profile_id}/stats instead."
          }
        },
        "type": "object",
        "required": [
          "profile_id",
          "status",
          "age_bucket",
          "gender",
          "geo",
          "created_at"
        ],
        "title": "DemographicProfileListItem",
        "description": "A single profile entry in GET /api/v1/b2b/profiles list response.\n\nIdentical to DemographicProfileStatusResponse but with ``cookie_jar`` omitted.\nCookie jars contain raw Google/YouTube session identity cookies\n(VISITOR_INFO1_LIVE, NID, PREF, YSC, SOCS, CONSENT) and must never be\nexposed in a collection endpoint.  Use GET /api/v1/b2b/profiles/{profile_id}\nto retrieve the cookie_jar for a specific completed profile."
      },
      "DemographicProfileListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/DemographicProfileListItem"
            },
            "type": "array",
            "title": "Items",
            "description": "Demographic profiles owned by the calling organisation."
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of profiles matching the applied filters (org_id + status).  Use with limit/offset to determine whether more pages exist."
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Maximum number of items returned in this response."
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Number of items skipped before this page."
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "True if there are more profiles beyond this page."
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "title": "DemographicProfileListResponse",
        "description": "Response body for GET /api/v1/b2b/profiles."
      },
      "DemographicProfileStatusResponse": {
        "properties": {
          "profile_id": {
            "type": "string",
            "title": "Profile Id",
            "description": "Profile identifier."
          },
          "status": {
            "type": "string",
            "enum": [
              "building",
              "complete",
              "failed"
            ],
            "title": "Status",
            "description": "'building' — warmup still in progress; 'complete' — cookie_jar and inferred demographics available; 'failed' — warmup failed."
          },
          "age_bucket": {
            "type": "string",
            "title": "Age Bucket",
            "description": "Target age range requested."
          },
          "gender": {
            "type": "string",
            "title": "Gender",
            "description": "Target gender requested ('F' or 'M')."
          },
          "geo": {
            "type": "string",
            "title": "Geo",
            "description": "Target geo code (ISO 3166-1 alpha-2)."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the build task was enqueued."
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Updated At",
            "description": "When the build state was last updated (None if still building)."
          },
          "last_verified_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Verified At",
            "description": "When the profile was last verified against adssettings.google.com (None if it has never been verified).  Set on each successful POST /profiles/{profile_id}/verify."
          },
          "inferred_age_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inferred Age Bucket",
            "description": "Age bucket inferred by Google for this profile (from adssettings.google.com).  Only present when status == 'complete'.  May differ from the requested age_bucket if warmup produced a weaker signal."
          },
          "inferred_gender": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inferred Gender",
            "description": "Gender inferred by Google ('Male'/'Female').  Only present when status == 'complete'."
          },
          "is_inferred": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Inferred",
            "description": "True when Google has registered at least one demographic attribute.  False when adssettings showed no inference (profile may need more warmup)."
          },
          "cookie_jar": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookie Jar",
            "description": "Flat {name: value} cookie dict for this demographic profile.  Only present when status == 'complete'.  Contains VISITOR_INFO1_LIVE, NID, PREF, YSC, SOCS, CONSENT."
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message when status == 'failed'.  None otherwise."
          }
        },
        "type": "object",
        "required": [
          "profile_id",
          "status",
          "age_bucket",
          "gender",
          "geo",
          "created_at"
        ],
        "title": "DemographicProfileStatusResponse",
        "description": "Response body for GET /api/v1/b2b/profiles/{profile_id}."
      },
      "DemographicProfileVerifyRequest": {
        "properties": {
          "proxy_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 512
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Url",
            "description": "Optional proxy URL (scheme://[user:pass@]host:port) for the verification browser.  When None, the worker's SERP_PROXY_URL env var is used."
          }
        },
        "type": "object",
        "title": "DemographicProfileVerifyRequest",
        "description": "Request body for POST /api/v1/b2b/profiles/{profile_id}/verify.\n\nTriggers a synchronous adssettings.google.com scrape to verify the\ndemographic that Google has inferred for the profile's cookie jar.\nThe result is stored back into the profile's Redis state and returned\nin the response.\n\nThis endpoint is a re-check — useful when the initial warmup returned\n``is_inferred=False`` and the caller wants to re-verify after more\nYouTube sessions have accumulated signal."
      },
      "DemographicProfileVerifyResponse": {
        "properties": {
          "profile_id": {
            "type": "string",
            "title": "Profile Id",
            "description": "Profile that was verified."
          },
          "is_inferred": {
            "type": "boolean",
            "title": "Is Inferred",
            "description": "True when Google inferred at least one demographic attribute."
          },
          "age_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Age Bucket",
            "description": "Age range inferred by Google, e.g. '18-24'.  None if not yet inferred."
          },
          "gender": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Gender",
            "description": "Gender inferred by Google — 'Male' or 'Female'.  None if not yet inferred."
          },
          "basis": {
            "type": "string",
            "title": "Basis",
            "description": "Source of inference: 'cookie' (expected for warmup profiles), 'account' (logged-in session detected), or 'none' (no signal found)."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable summary of the verification result."
          }
        },
        "type": "object",
        "required": [
          "profile_id",
          "is_inferred",
          "basis",
          "message"
        ],
        "title": "DemographicProfileVerifyResponse",
        "description": "Response body for POST /api/v1/b2b/profiles/{profile_id}/verify."
      },
      "DepositHistoryItem": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "stripe_session_id": {
            "type": "string",
            "title": "Stripe Session Id"
          },
          "amount_cents": {
            "type": "integer",
            "title": "Amount Cents"
          },
          "amount_display": {
            "type": "string",
            "title": "Amount Display"
          },
          "currency": {
            "type": "string",
            "title": "Currency"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "payment_method_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Method Display"
          },
          "receipt_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Receipt Url"
          },
          "balance_after_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Balance After Microcents"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "stripe_session_id",
          "amount_cents",
          "amount_display",
          "currency",
          "status",
          "created_at"
        ],
        "title": "DepositHistoryItem",
        "description": "A single completed deposit (checkout session + ledger grant) for display."
      },
      "DepositHistoryResponse": {
        "properties": {
          "deposits": {
            "items": {
              "$ref": "#/components/schemas/DepositHistoryItem"
            },
            "type": "array",
            "title": "Deposits"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "deposits",
          "total"
        ],
        "title": "DepositHistoryResponse",
        "description": "Paginated deposit history."
      },
      "DepositRequest": {
        "properties": {
          "amount_cents": {
            "type": "integer",
            "maximum": 200000.0,
            "minimum": 1000.0,
            "title": "Amount Cents",
            "description": "Amount to deposit in cents ($10-$2000)"
          },
          "success_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Success Url"
          },
          "cancel_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancel Url"
          },
          "promo_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Promo Code"
          },
          "auto_recharge_enabled": {
            "type": "boolean",
            "title": "Auto Recharge Enabled",
            "description": "If true, enable auto-recharge after successful deposit",
            "default": false
          },
          "auto_recharge_threshold_microcents": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 50000000000.0,
                "minimum": 100000000.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Recharge Threshold Microcents",
            "description": "Balance threshold that triggers auto-recharge (in microcents). Defaults to smart value if omitted."
          },
          "auto_recharge_amount_cents": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 200000.0,
                "minimum": 2500.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Recharge Amount Cents",
            "description": "Amount to recharge in cents ($25-$2000). Must be >= $25 (2500 cents) to satisfy DB constraint."
          }
        },
        "type": "object",
        "required": [
          "amount_cents"
        ],
        "title": "DepositRequest",
        "description": "Deposit funds request."
      },
      "DepositResponse": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "amount_cents": {
            "type": "integer",
            "title": "Amount Cents"
          },
          "amount_display": {
            "type": "string",
            "title": "Amount Display"
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "url",
          "amount_cents",
          "amount_display"
        ],
        "title": "DepositResponse",
        "description": "Deposit checkout response."
      },
      "DetailedJobResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "mode": {
            "type": "string",
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration Ms"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status Code"
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Type"
          },
          "content_length": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Length"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "error_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Code"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached",
            "default": false
          },
          "proxy_used": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Used"
          },
          "js_rendered": {
            "type": "boolean",
            "title": "Js Rendered",
            "default": false
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "webhook_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Status"
          },
          "result_preview": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result Preview"
          },
          "has_result": {
            "type": "boolean",
            "title": "Has Result",
            "default": false
          },
          "request_options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Options"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "mode",
          "status",
          "credits_used",
          "created_at"
        ],
        "title": "DetailedJobResponse",
        "description": "Detailed job response with full information."
      },
      "DeviceFingerprint": {
        "properties": {
          "visitor_id": {
            "type": "string",
            "title": "Visitor Id",
            "description": "FingerprintJS visitor ID or hash"
          },
          "confidence": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 1.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Confidence",
            "description": "Confidence score 0-1"
          },
          "components": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Components",
            "description": "Individual fingerprint components (canvas, webgl, etc.)"
          }
        },
        "type": "object",
        "required": [
          "visitor_id"
        ],
        "title": "DeviceFingerprint",
        "description": "Device fingerprint data collected from client."
      },
      "DisconnectResponse": {
        "properties": {
          "disconnected": {
            "type": "boolean",
            "title": "Disconnected"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          }
        },
        "type": "object",
        "required": [
          "disconnected",
          "provider"
        ],
        "title": "DisconnectResponse"
      },
      "DismissRequest": {
        "properties": {
          "notification_id": {
            "type": "string",
            "format": "uuid",
            "title": "Notification Id"
          }
        },
        "type": "object",
        "required": [
          "notification_id"
        ],
        "title": "DismissRequest"
      },
      "DomainAnalyticsItem": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests"
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          },
          "last_seen": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Seen"
          },
          "first_seen": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Seen"
          },
          "trend": {
            "type": "string",
            "title": "Trend"
          },
          "requests_change_percent": {
            "type": "number",
            "title": "Requests Change Percent"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "total_requests",
          "successful_requests",
          "failed_requests",
          "success_rate",
          "total_credits",
          "trend",
          "requests_change_percent"
        ],
        "title": "DomainAnalyticsItem",
        "description": "Per-domain analytics summary."
      },
      "DomainAnalyticsResponse": {
        "properties": {
          "domains": {
            "items": {
              "$ref": "#/components/schemas/DomainAnalyticsItem"
            },
            "type": "array",
            "title": "Domains"
          },
          "total_domains": {
            "type": "integer",
            "title": "Total Domains"
          }
        },
        "type": "object",
        "required": [
          "domains",
          "total_domains"
        ],
        "title": "DomainAnalyticsResponse",
        "description": "Domain analytics list response."
      },
      "DomainDetailResponse": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests"
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          },
          "min_response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Response Time Ms"
          },
          "max_response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Response Time Ms"
          },
          "cache_hit_rate": {
            "type": "number",
            "title": "Cache Hit Rate"
          },
          "cached_requests": {
            "type": "integer",
            "title": "Cached Requests"
          },
          "last_seen": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Seen"
          },
          "first_seen": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Seen"
          },
          "errors": {
            "items": {
              "$ref": "#/components/schemas/DomainErrorItem"
            },
            "type": "array",
            "title": "Errors"
          },
          "status_codes": {
            "items": {
              "$ref": "#/components/schemas/DomainStatusCodeItem"
            },
            "type": "array",
            "title": "Status Codes"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "total_requests",
          "successful_requests",
          "failed_requests",
          "success_rate",
          "total_credits",
          "cache_hit_rate",
          "cached_requests",
          "errors",
          "status_codes"
        ],
        "title": "DomainDetailResponse",
        "description": "Detailed analytics for a single domain."
      },
      "DomainErrorItem": {
        "properties": {
          "error_type": {
            "type": "string",
            "title": "Error Type"
          },
          "raw_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Raw Error"
          },
          "count": {
            "type": "integer",
            "title": "Count"
          }
        },
        "type": "object",
        "required": [
          "error_type",
          "count"
        ],
        "title": "DomainErrorItem",
        "description": "Domain error breakdown item."
      },
      "DomainStatusCodeItem": {
        "properties": {
          "code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Code"
          },
          "count": {
            "type": "integer",
            "title": "Count"
          }
        },
        "type": "object",
        "required": [
          "count"
        ],
        "title": "DomainStatusCodeItem",
        "description": "Domain status code item."
      },
      "DomainTimeseriesPoint": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "successes": {
            "type": "integer",
            "title": "Successes"
          },
          "failures": {
            "type": "integer",
            "title": "Failures"
          },
          "credits": {
            "type": "integer",
            "title": "Credits"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          }
        },
        "type": "object",
        "required": [
          "date",
          "requests",
          "successes",
          "failures",
          "credits",
          "success_rate"
        ],
        "title": "DomainTimeseriesPoint",
        "description": "Domain time-series data point."
      },
      "DomainTimeseriesResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/DomainTimeseriesPoint"
            },
            "type": "array",
            "title": "Data"
          },
          "period_start": {
            "type": "string",
            "title": "Period Start"
          },
          "period_end": {
            "type": "string",
            "title": "Period End"
          }
        },
        "type": "object",
        "required": [
          "data",
          "period_start",
          "period_end"
        ],
        "title": "DomainTimeseriesResponse",
        "description": "Domain time-series response."
      },
      "EarningsSummaryResponse": {
        "properties": {
          "total_earned_cents": {
            "type": "integer",
            "title": "Total Earned Cents"
          },
          "pending_balance_cents": {
            "type": "integer",
            "title": "Pending Balance Cents"
          },
          "paid_cents": {
            "type": "integer",
            "title": "Paid Cents"
          },
          "yearly_earnings_cents": {
            "type": "integer",
            "title": "Yearly Earnings Cents"
          },
          "is_1099_eligible": {
            "type": "boolean",
            "title": "Is 1099 Eligible"
          },
          "onboarding_status": {
            "type": "string",
            "title": "Onboarding Status"
          },
          "kyc_verified": {
            "type": "boolean",
            "title": "Kyc Verified"
          },
          "recent_payouts": {
            "items": {},
            "type": "array",
            "title": "Recent Payouts"
          }
        },
        "type": "object",
        "required": [
          "total_earned_cents",
          "pending_balance_cents",
          "paid_cents",
          "yearly_earnings_cents",
          "is_1099_eligible",
          "onboarding_status",
          "kyc_verified",
          "recent_payouts"
        ],
        "title": "EarningsSummaryResponse",
        "description": "GET /creator/earnings response."
      },
      "EmailCheckRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "EmailCheckRequest"
      },
      "EmailCheckResponse": {
        "properties": {
          "exists": {
            "type": "boolean",
            "title": "Exists"
          },
          "has_password": {
            "type": "boolean",
            "title": "Has Password"
          }
        },
        "type": "object",
        "required": [
          "exists",
          "has_password"
        ],
        "title": "EmailCheckResponse"
      },
      "EmbeddingChunk": {
        "properties": {
          "text": {
            "type": "string",
            "title": "Text",
            "description": "The chunk text that was embedded"
          },
          "embedding": {
            "items": {
              "type": "number"
            },
            "type": "array",
            "title": "Embedding",
            "description": "The embedding vector"
          },
          "start_index": {
            "type": "integer",
            "title": "Start Index",
            "description": "Character start index in the original text"
          },
          "end_index": {
            "type": "integer",
            "title": "End Index",
            "description": "Character end index in the original text"
          }
        },
        "type": "object",
        "required": [
          "text",
          "embedding",
          "start_index",
          "end_index"
        ],
        "title": "EmbeddingChunk",
        "description": "A single embedded chunk of text."
      },
      "EmbeddingsConfig": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Enable embedding generation for scraped content (+$0.001 per page)",
            "default": false
          },
          "model": {
            "type": "string",
            "enum": [
              "text-embedding-3-small",
              "text-embedding-3-large"
            ],
            "title": "Model",
            "description": "OpenAI embedding model. text-embedding-3-small (1536 dims, cheapest) or text-embedding-3-large (3072 dims, best quality)",
            "default": "text-embedding-3-small"
          },
          "chunk_size": {
            "type": "integer",
            "maximum": 8191.0,
            "minimum": 64.0,
            "title": "Chunk Size",
            "description": "Target chunk size in tokens for text splitting (64-8191)",
            "default": 512
          },
          "chunk_overlap": {
            "type": "integer",
            "maximum": 2048.0,
            "minimum": 0.0,
            "title": "Chunk Overlap",
            "description": "Overlap between chunks in tokens (0-2048)",
            "default": 50
          }
        },
        "type": "object",
        "title": "EmbeddingsConfig",
        "description": "Configuration for optional inline embeddings generation.\n\nWhen enabled, scraped text content is chunked and embedded using OpenAI\nembedding models. Results are included in the scrape response.\n\nAdd-on cost: +$0.001 per page (1000 microcents)."
      },
      "EmbeddingsResult": {
        "properties": {
          "model": {
            "type": "string",
            "title": "Model",
            "description": "Embedding model used"
          },
          "dimensions": {
            "type": "integer",
            "title": "Dimensions",
            "description": "Embedding vector dimensions"
          },
          "chunks": {
            "items": {
              "$ref": "#/components/schemas/EmbeddingChunk"
            },
            "type": "array",
            "title": "Chunks",
            "description": "Embedded text chunks"
          },
          "total_tokens": {
            "type": "integer",
            "title": "Total Tokens",
            "description": "Total tokens processed by the embedding model"
          },
          "total_chunks": {
            "type": "integer",
            "title": "Total Chunks",
            "description": "Number of chunks generated"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached",
            "description": "Whether embeddings were served from cache",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "model",
          "dimensions",
          "chunks",
          "total_tokens",
          "total_chunks"
        ],
        "title": "EmbeddingsResult",
        "description": "Embeddings result included in scrape response."
      },
      "EndpointTimeseriesPoint": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "scrape": {
            "type": "integer",
            "title": "Scrape",
            "default": 0
          },
          "crawl": {
            "type": "integer",
            "title": "Crawl",
            "default": 0
          },
          "map": {
            "type": "integer",
            "title": "Map",
            "default": 0
          },
          "search": {
            "type": "integer",
            "title": "Search",
            "default": 0
          },
          "extract": {
            "type": "integer",
            "title": "Extract",
            "default": 0
          },
          "scrape_credits": {
            "type": "integer",
            "title": "Scrape Credits",
            "default": 0
          },
          "crawl_credits": {
            "type": "integer",
            "title": "Crawl Credits",
            "default": 0
          },
          "map_credits": {
            "type": "integer",
            "title": "Map Credits",
            "default": 0
          },
          "search_credits": {
            "type": "integer",
            "title": "Search Credits",
            "default": 0
          },
          "extract_credits": {
            "type": "integer",
            "title": "Extract Credits",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "date"
        ],
        "title": "EndpointTimeseriesPoint",
        "description": "Per-endpoint-type timeseries data point."
      },
      "EndpointTimeseriesResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/EndpointTimeseriesPoint"
            },
            "type": "array",
            "title": "Data"
          },
          "period_start": {
            "type": "string",
            "title": "Period Start"
          },
          "period_end": {
            "type": "string",
            "title": "Period End"
          }
        },
        "type": "object",
        "required": [
          "data",
          "period_start",
          "period_end"
        ],
        "title": "EndpointTimeseriesResponse",
        "description": "Endpoint type timeseries response."
      },
      "EndpointTypeStatsItem": {
        "properties": {
          "endpoint_type": {
            "type": "string",
            "title": "Endpoint Type"
          },
          "request_count": {
            "type": "integer",
            "title": "Request Count"
          },
          "success_count": {
            "type": "integer",
            "title": "Success Count"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          },
          "extra": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extra"
          }
        },
        "type": "object",
        "required": [
          "endpoint_type",
          "request_count",
          "success_count",
          "success_rate",
          "total_credits"
        ],
        "title": "EndpointTypeStatsItem",
        "description": "Per-endpoint-type usage statistics."
      },
      "EndpointTypeStatsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/EndpointTypeStatsItem"
            },
            "type": "array",
            "title": "Data"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          }
        },
        "type": "object",
        "required": [
          "data",
          "total_requests",
          "total_credits"
        ],
        "title": "EndpointTypeStatsResponse",
        "description": "Endpoint type stats response."
      },
      "EnrollmentContactRunItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid",
            "title": "Contact Id"
          },
          "contact_email": {
            "type": "string",
            "title": "Contact Email"
          },
          "contact_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Contact Name"
          },
          "run_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Run Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "contact_id",
          "contact_email",
          "contact_name",
          "run_id",
          "status",
          "error",
          "started_at",
          "completed_at",
          "created_at"
        ],
        "title": "EnrollmentContactRunItem",
        "description": "Per-contact run status within an enrollment."
      },
      "EnrollmentContactRunListResponse": {
        "properties": {
          "contacts": {
            "items": {
              "$ref": "#/components/schemas/EnrollmentContactRunItem"
            },
            "type": "array",
            "title": "Contacts"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages"
          }
        },
        "type": "object",
        "required": [
          "contacts",
          "total",
          "page",
          "limit",
          "total_pages"
        ],
        "title": "EnrollmentContactRunListResponse",
        "description": "GET /workflows/{id}/sequences/{enrollment_id}/contacts response."
      },
      "EnrollmentContactRunUpdate": {
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "paused",
              "active"
            ],
            "title": "Status",
            "description": "'paused' = skip this contact; 'active' = re-enable a paused contact"
          }
        },
        "type": "object",
        "required": [
          "status"
        ],
        "title": "EnrollmentContactRunUpdate",
        "description": "PATCH /workflows/{id}/sequences/{enrollment_id}/contacts/{contact_id} body."
      },
      "EnterpriseAcceptRequest": {
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1,
            "title": "Token",
            "description": "Enterprise invite token from the magic link"
          },
          "password": {
            "type": "string",
            "minLength": 10,
            "title": "Password",
            "description": "Password to set for the account (validated against NIST SP 800-63B rules)"
          }
        },
        "type": "object",
        "required": [
          "token",
          "password"
        ],
        "title": "EnterpriseAcceptRequest",
        "description": "Request body for POST /auth/enterprise-accept.\n\nRedeems a one-time enterprise invite token, sets the client's password,\nmarks their email as verified, and returns a session."
      },
      "EnterpriseAcceptResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "email_verified": {
            "type": "boolean",
            "title": "Email Verified"
          },
          "is_admin": {
            "type": "boolean",
            "title": "Is Admin",
            "default": false
          },
          "session_token": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Token"
          },
          "org_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Id"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email",
          "name",
          "email_verified"
        ],
        "title": "EnterpriseAcceptResponse",
        "description": "Extended auth response for enterprise invite acceptance.\n\nIncludes org_id so the frontend can switch to the enterprise org context\nbefore redirecting — prevents falling back to the personal org."
      },
      "EnterpriseInviteInfoResponse": {
        "properties": {
          "client_email": {
            "type": "string",
            "title": "Client Email"
          },
          "org_name": {
            "type": "string",
            "title": "Org Name"
          },
          "is_valid": {
            "type": "boolean",
            "title": "Is Valid",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "client_email",
          "org_name"
        ],
        "title": "EnterpriseInviteInfoResponse",
        "description": "Response for GET /auth/enterprise-invite/{token}.\n\nReturns invite metadata so the frontend can pre-fill the activation form.\nNo auth required — the invite token is the credential."
      },
      "ErasureResult": {
        "properties": {
          "email": {
            "type": "string",
            "title": "Email",
            "description": "Normalised email that was erased"
          },
          "contacts_deleted": {
            "type": "integer",
            "title": "Contacts Deleted",
            "description": "Number of contact records deleted"
          },
          "lists_affected": {
            "type": "integer",
            "title": "Lists Affected",
            "description": "Number of distinct contact lists affected"
          }
        },
        "type": "object",
        "required": [
          "email",
          "contacts_deleted",
          "lists_affected"
        ],
        "title": "ErasureResult",
        "description": "Result of an erasure request."
      },
      "ErrorBreakdownItem": {
        "properties": {
          "category": {
            "type": "string",
            "title": "Category"
          },
          "count": {
            "type": "integer",
            "title": "Count",
            "default": 0
          },
          "percentage": {
            "type": "number",
            "title": "Percentage",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "category"
        ],
        "title": "ErrorBreakdownItem",
        "description": "Single error category in the breakdown."
      },
      "ErrorBreakdownResponse": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "days": {
            "type": "integer",
            "title": "Days"
          },
          "total_errors": {
            "type": "integer",
            "title": "Total Errors",
            "default": 0
          },
          "errors": {
            "items": {
              "$ref": "#/components/schemas/ErrorBreakdownItem"
            },
            "type": "array",
            "title": "Errors"
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "days",
          "errors"
        ],
        "title": "ErrorBreakdownResponse",
        "description": "Response for per-key error breakdown."
      },
      "EstimateBreakdown": {
        "properties": {
          "base_cost_microcents": {
            "type": "integer",
            "title": "Base Cost Microcents",
            "description": "Content transformation cost (ContentTransformer pipeline)"
          },
          "llm_cost_microcents": {
            "type": "integer",
            "title": "Llm Cost Microcents",
            "description": "LLM invocation fee (0 when has_extraction_prompt is false)"
          },
          "min_charge_microcents": {
            "type": "integer",
            "title": "Min Charge Microcents",
            "description": "Minimum charge enforced per extraction call",
            "default": 100
          },
          "max_charge_microcents": {
            "type": "integer",
            "title": "Max Charge Microcents",
            "description": "Maximum charge cap per extraction call",
            "default": 50000
          }
        },
        "type": "object",
        "required": [
          "base_cost_microcents",
          "llm_cost_microcents"
        ],
        "title": "EstimateBreakdown",
        "description": "Cost breakdown for GET /v1/extract/estimate."
      },
      "EstimateResponse": {
        "properties": {
          "estimated_cost_microcents": {
            "type": "integer",
            "title": "Estimated Cost Microcents",
            "description": "Estimated total cost in microcents. Clamped to [100, 50000] µ¢. Actual cost may differ if content size changes or if a BYOK invocation fee applies."
          },
          "estimated_cost_usd": {
            "type": "string",
            "title": "Estimated Cost Usd",
            "description": "Estimated cost formatted as USD string (e.g. '$0.0025')"
          },
          "breakdown": {
            "$ref": "#/components/schemas/EstimateBreakdown",
            "description": "Per-component cost breakdown"
          }
        },
        "type": "object",
        "required": [
          "estimated_cost_microcents",
          "estimated_cost_usd",
          "breakdown"
        ],
        "title": "EstimateResponse",
        "description": "Response from GET /v1/extract/estimate."
      },
      "EvaluateAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "evaluate",
            "title": "Type",
            "default": "evaluate"
          },
          "script": {
            "type": "string",
            "maxLength": 5120,
            "title": "Script",
            "description": "JavaScript to execute in page context (max 5120 chars). Network APIs (fetch, XMLHttpRequest, WebSocket) and dynamic code execution (eval, Function constructor) are blocked."
          }
        },
        "type": "object",
        "required": [
          "script"
        ],
        "title": "EvaluateAction",
        "description": "Execute custom JavaScript in the page context.\n\nScripts are validated against a blocklist of dangerous patterns that could\nenable SSRF (fetching internal endpoints from the worker network) or\narbitrary code generation (eval/Function constructors)."
      },
      "ExchangeSessionTokenRequest": {
        "properties": {
          "session_token": {
            "type": "string",
            "title": "Session Token"
          }
        },
        "type": "object",
        "required": [
          "session_token"
        ],
        "title": "ExchangeSessionTokenRequest",
        "description": "Request to exchange a session token for user data (used by NextAuth after OTP verification)."
      },
      "ExtractRequest": {
        "properties": {
          "content": {
            "type": "string",
            "maxLength": 500000,
            "minLength": 1,
            "title": "Content",
            "description": "Raw content to extract from (HTML, text, markdown, or base64-encoded PDF)"
          },
          "content_type": {
            "type": "string",
            "enum": [
              "html",
              "text",
              "markdown"
            ],
            "title": "Content Type",
            "description": "Type of the provided content",
            "default": "html"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON Schema for structured extraction. Fields are mapped from content."
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Pre-defined extraction profile (schema template)"
          },
          "extraction_template": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Template",
            "description": "Shorthand for extraction_profile. Selects a pre-built schema template by name. Mutually exclusive with extraction_profile."
          },
          "extraction_prompt": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Prompt",
            "description": "Natural language extraction instructions for the LLM"
          },
          "extraction_provider": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "openai",
                  "anthropic",
                  "openrouter",
                  "groq"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Provider",
            "description": "LLM provider to use for extraction. Selects the matching BYOK key registered at /dashboard/settings/llm-keys. When omitted, the most recently used registered key is used automatically."
          },
          "extraction_model": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Model",
            "description": "Per-request LLM model override in provider-specific format (e.g. 'gpt-4o', 'claude-opus-4-5-20251101', 'llama3-70b-8192'). When provided, overrides the model saved in your BYOK key settings for this request only. When omitted, the model configured on your registered key is used."
          },
          "formats": {
            "items": {
              "type": "string",
              "enum": [
                "text",
                "json",
                "json_v2",
                "html",
                "markdown",
                "rag",
                "content",
                "raw"
              ]
            },
            "type": "array",
            "minItems": 1,
            "title": "Formats",
            "description": "Output formats for content transformation",
            "default": [
              "json"
            ]
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Original URL of the content (for context, not fetched)"
          },
          "evidence": {
            "type": "boolean",
            "title": "Evidence",
            "description": "Include field provenance/evidence for extracted fields",
            "default": false
          },
          "cache": {
            "type": "string",
            "enum": [
              "auto",
              "skip",
              "only"
            ],
            "title": "Cache",
            "description": "Cache control for LLM extraction results. auto: return cached result if available (default). skip: bypass cache lookup, always call LLM (result is still stored for future callers). only: return cached result or HTTP 404 if not cached — never calls the LLM.",
            "default": "auto"
          },
          "cache_ttl": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 86400.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Cache Ttl",
            "description": "TTL for caching this extraction result, in seconds. Defaults to LLM_EXTRACTION_CACHE_TTL env var (3600s). Max 86400s (24 hours)."
          }
        },
        "type": "object",
        "required": [
          "content"
        ],
        "title": "ExtractRequest",
        "description": "Request body for POST /v1/extract — standalone LLM extraction from raw content."
      },
      "ExtractResponse": {
        "properties": {
          "extract_id": {
            "type": "string",
            "title": "Extract Id",
            "description": "Unique identifier for this extraction"
          },
          "formats": {
            "additionalProperties": true,
            "type": "object",
            "title": "Formats",
            "description": "Extraction results keyed by requested format"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Account credits charged for this extraction call"
          },
          "model_used": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model Used",
            "description": "LLM model used for extraction (if extraction_prompt was provided)"
          },
          "extraction_method": {
            "type": "string",
            "title": "Extraction Method",
            "description": "Method used: algorithmic, llm, playbook, lossless",
            "default": "algorithmic"
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Extraction profile applied (if any): auto, product, article, job_posting, faq, recipe, event, ecommerce_homepage, directory_listing"
          },
          "content_size_chars": {
            "type": "integer",
            "title": "Content Size Chars",
            "description": "Size of the input content in characters"
          },
          "extraction_metadata": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExtractionMetadata"
              },
              {
                "type": "null"
              }
            ],
            "description": "Full extraction context including provider, model, token usage, invocation cost, latency, and cache status. Populated on every call."
          },
          "cache_hit": {
            "type": "boolean",
            "title": "Cache Hit",
            "description": "True when the LLM extraction result was served from Redis cache. When True, no LLM call was made and the BYOK invocation fee was not charged.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "extract_id",
          "formats",
          "credits_used",
          "content_size_chars"
        ],
        "title": "ExtractResponse",
        "description": "Response from POST /v1/extract."
      },
      "ExtractionHealthResponse": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "api_key_set": {
            "type": "boolean",
            "title": "Api Key Set"
          },
          "model": {
            "type": "string",
            "title": "Model"
          },
          "base_url": {
            "type": "string",
            "title": "Base Url"
          },
          "byok_available": {
            "type": "boolean",
            "title": "Byok Available",
            "default": true
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "title": "Timestamp"
          }
        },
        "type": "object",
        "required": [
          "enabled",
          "api_key_set",
          "model",
          "base_url"
        ],
        "title": "ExtractionHealthResponse",
        "description": "LLM extraction readiness response.\n\nReports the configuration state of the LLM extraction feature without\nexposing any secret values. Requires authentication."
      },
      "ExtractionMetadata": {
        "properties": {
          "mode": {
            "type": "string",
            "title": "Mode",
            "description": "Extraction mode: 'byok' when BYOK key was used, 'algorithmic' otherwise"
          },
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider",
            "description": "LLM provider used (openai, anthropic, openrouter, groq), or null if no LLM ran"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "LLM model ID used for extraction, or null if no LLM ran"
          },
          "input_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Tokens",
            "description": "Prompt token count reported by the provider, or null if unavailable"
          },
          "output_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Output Tokens",
            "description": "Completion token count reported by the provider, or null if unavailable"
          },
          "cost_microcents": {
            "type": "integer",
            "title": "Cost Microcents",
            "description": "AlterLab invocation fee charged in microcents (net of any refunds)"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached",
            "description": "Whether a cached extraction result was served",
            "default": false
          },
          "latency_ms": {
            "type": "integer",
            "title": "Latency Ms",
            "description": "End-to-end extraction latency in milliseconds"
          }
        },
        "type": "object",
        "required": [
          "mode",
          "cost_microcents",
          "latency_ms"
        ],
        "title": "ExtractionMetadata",
        "description": "Per-call extraction transparency metadata returned in POST /v1/extract responses.\n\nProvides full context about how the extraction was performed: which LLM provider\nand model were used, token counts reported by the provider, AlterLab's invocation\nfee, end-to-end latency, and whether a cached result was served.\n\nToken counts are ``None`` when no LLM was invoked (algorithmic extraction) or when\nthe provider did not report usage (some OpenRouter models omit usage fields)."
      },
      "ExtractionStatus": {
        "properties": {
          "has_byok_key": {
            "type": "boolean",
            "title": "Has Byok Key"
          },
          "byok_providers": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Byok Providers"
          },
          "extraction_enabled": {
            "type": "boolean",
            "title": "Extraction Enabled"
          },
          "extraction_rate_limit": {
            "type": "integer",
            "title": "Extraction Rate Limit"
          }
        },
        "type": "object",
        "required": [
          "has_byok_key",
          "byok_providers",
          "extraction_enabled",
          "extraction_rate_limit"
        ],
        "title": "ExtractionStatus",
        "description": "BYOK extraction capability summary for the authenticated user.\n\nReturned as part of UserResponse so the dashboard can render the correct\nextraction UI without making a separate API call."
      },
      "ExtractionUsageListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/ExtractionUsageRecord"
            },
            "type": "array",
            "title": "Items",
            "description": "Extraction usage records for the requested page"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of records matching the filter"
          },
          "page": {
            "type": "integer",
            "title": "Page",
            "description": "Current page (1-indexed)"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size",
            "description": "Number of records per page"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "True when additional pages are available beyond the current page"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "page_size",
          "has_more"
        ],
        "title": "ExtractionUsageListResponse",
        "description": "Paginated list of extraction usage records."
      },
      "ExtractionUsageRecord": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Unique extraction usage record ID (UUID)"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "Timestamp of the extraction call (UTC)"
          },
          "extraction_mode": {
            "type": "string",
            "title": "Extraction Mode",
            "description": "Extraction mode: 'byok' for Bring Your Own Key, 'platform' for managed"
          },
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider",
            "description": "LLM provider used (openai, anthropic, openrouter, groq), or null"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "LLM model ID used, or null when no LLM ran"
          },
          "input_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Tokens",
            "description": "Prompt token count reported by the provider"
          },
          "output_tokens": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Output Tokens",
            "description": "Completion token count reported by the provider"
          },
          "billed_cost_microcents": {
            "type": "integer",
            "title": "Billed Cost Microcents",
            "description": "AlterLab invocation fee charged for this call (microcents)"
          },
          "latency_ms": {
            "type": "integer",
            "title": "Latency Ms",
            "description": "End-to-end extraction latency in milliseconds"
          },
          "domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain",
            "description": "Target domain if triggered via /v1/scrape, otherwise null"
          },
          "has_schema": {
            "type": "boolean",
            "title": "Has Schema",
            "description": "True when extraction_schema was provided (structured extraction)"
          },
          "success": {
            "type": "boolean",
            "title": "Success",
            "description": "True when extraction produced a parseable result"
          },
          "error_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Type",
            "description": "Error classification if not successful: timeout, auth_error, parse_error, rate_limit"
          }
        },
        "type": "object",
        "required": [
          "id",
          "created_at",
          "extraction_mode",
          "billed_cost_microcents",
          "latency_ms",
          "has_schema",
          "success"
        ],
        "title": "ExtractionUsageRecord",
        "description": "Single row from the extraction_usage table, returned in history responses."
      },
      "ExtractionUsageSummaryResponse": {
        "properties": {
          "total_requests": {
            "type": "integer",
            "title": "Total Requests",
            "description": "Total number of extraction invocations in the period"
          },
          "total_cost_microcents": {
            "type": "integer",
            "title": "Total Cost Microcents",
            "description": "Sum of billed_cost_microcents for all extraction invocations in the period"
          }
        },
        "type": "object",
        "required": [
          "total_requests",
          "total_cost_microcents"
        ],
        "title": "ExtractionUsageSummaryResponse",
        "description": "Aggregate extraction usage totals for a time period.\n\nReturned by GET /api/v1/extract/usage/summary — counts ALL records matching\nthe filter, not just a page window. Use this for overview cards so the\ndisplayed totals always reflect the full selected period."
      },
      "FeaturedSnippetResponse": {
        "properties": {
          "content": {
            "type": "string",
            "title": "Content",
            "description": "Snippet text content"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Source page URL"
          },
          "source_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Title",
            "description": "Source page title"
          },
          "snippet_type": {
            "type": "string",
            "title": "Snippet Type",
            "description": "Type: text, list, or table",
            "default": "text"
          }
        },
        "type": "object",
        "required": [
          "content"
        ],
        "title": "FeaturedSnippetResponse",
        "description": "Featured snippet / answer box at the top of search results."
      },
      "FeedbackIssueType": {
        "type": "string",
        "enum": [
          "captcha_page",
          "incomplete_scrape",
          "blocked",
          "wrong_content",
          "slow_response",
          "extraction_error",
          "encoding_error",
          "other"
        ],
        "title": "FeedbackIssueType",
        "description": "Types of issues users can report about scrape results.\n\nThese map to the UI dropdown options in the Playground."
      },
      "FillAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "fill",
            "title": "Type",
            "default": "fill"
          },
          "selector": {
            "type": "string",
            "maxLength": 500,
            "title": "Selector",
            "description": "CSS selector of input element"
          },
          "value": {
            "type": "string",
            "maxLength": 5000,
            "title": "Value",
            "description": "Value to fill into the input"
          }
        },
        "type": "object",
        "required": [
          "selector",
          "value"
        ],
        "title": "FillAction",
        "description": "Fill an input field with a value."
      },
      "FirecrawlCrawlPageData": {
        "properties": {
          "markdown": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Markdown"
          },
          "html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Html"
          },
          "rawHtml": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rawhtml"
          },
          "links": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Links"
          },
          "screenshot": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Screenshot"
          },
          "metadata": {
            "$ref": "#/components/schemas/FirecrawlMetadata"
          }
        },
        "type": "object",
        "title": "FirecrawlCrawlPageData",
        "description": "A single page result in a Firecrawl crawl status response."
      },
      "FirecrawlCrawlRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "The URL to crawl"
          },
          "excludePaths": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Excludepaths",
            "description": "URL path patterns to exclude from the crawl"
          },
          "includePaths": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Includepaths",
            "description": "URL path patterns to include in the crawl"
          },
          "maxDepth": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 0.0,
            "title": "Maxdepth",
            "description": "Maximum depth to crawl relative to the entered URL",
            "default": 2
          },
          "ignoreSitemap": {
            "type": "boolean",
            "title": "Ignoresitemap",
            "description": "Ignore the website sitemap when crawling",
            "default": false
          },
          "limit": {
            "type": "integer",
            "maximum": 100000.0,
            "minimum": 1.0,
            "title": "Limit",
            "description": "Maximum number of pages to crawl",
            "default": 10
          },
          "scrapeOptions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FirecrawlCrawlScrapeOptions"
              },
              {
                "type": "null"
              }
            ],
            "description": "Scrape options to apply to each page"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "FirecrawlCrawlRequest",
        "description": "Firecrawl-compatible crawl request.\n\nMaps to Firecrawl's POST /crawl endpoint format."
      },
      "FirecrawlCrawlResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "default": true
          },
          "id": {
            "type": "string",
            "title": "Id",
            "description": "Crawl job ID for polling"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "URL to poll for status (e.g. /v0/crawl/{id})"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url"
        ],
        "title": "FirecrawlCrawlResponse",
        "description": "Firecrawl-compatible crawl start response (202 Accepted)."
      },
      "FirecrawlCrawlScrapeOptions": {
        "properties": {
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "markdown",
                    "html",
                    "rawHtml",
                    "links",
                    "screenshot",
                    "extract",
                    "json"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats for each page",
            "default": [
              "markdown"
            ]
          },
          "onlyMainContent": {
            "type": "boolean",
            "title": "Onlymaincontent",
            "description": "Only return main content",
            "default": true
          },
          "waitFor": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Waitfor",
            "description": "Wait time in ms",
            "default": 0
          }
        },
        "type": "object",
        "title": "FirecrawlCrawlScrapeOptions",
        "description": "Scrape options embedded in a Firecrawl crawl request."
      },
      "FirecrawlCrawlStatusResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "default": true
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Crawl status: scraping, completed, failed, cancelled"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total pages discovered",
            "default": 0
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "description": "Pages successfully scraped",
            "default": 0
          },
          "creditsUsed": {
            "type": "integer",
            "title": "Creditsused",
            "description": "Total credits consumed",
            "default": 0
          },
          "expiresAt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiresat",
            "description": "When crawl data expires"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/FirecrawlCrawlPageData"
            },
            "type": "array",
            "title": "Data",
            "description": "Scraped page results (populated when completed)"
          },
          "alterlab": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alterlab",
            "description": "AlterLab-specific metadata (crawl_id, billing, etc.)"
          }
        },
        "type": "object",
        "required": [
          "status"
        ],
        "title": "FirecrawlCrawlStatusResponse",
        "description": "Firecrawl-compatible crawl status response."
      },
      "FirecrawlErrorResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "default": false
          },
          "error": {
            "type": "string",
            "title": "Error"
          },
          "details": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Details"
          }
        },
        "type": "object",
        "required": [
          "error"
        ],
        "title": "FirecrawlErrorResponse",
        "description": "Firecrawl-compatible error response."
      },
      "FirecrawlMapRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "The URL to map"
          },
          "search": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Search",
            "description": "Search query to filter and rank discovered URLs by relevance"
          },
          "ignoreSitemap": {
            "type": "boolean",
            "title": "Ignoresitemap",
            "description": "Ignore the website sitemap when crawling",
            "default": false
          },
          "sitemapOnly": {
            "type": "boolean",
            "title": "Sitemaponly",
            "description": "Only return URLs found in the sitemap",
            "default": false
          },
          "includeSubdomains": {
            "type": "boolean",
            "title": "Includesubdomains",
            "description": "Include subdomains of the website",
            "default": false
          },
          "limit": {
            "type": "integer",
            "maximum": 50000.0,
            "minimum": 1.0,
            "title": "Limit",
            "description": "Maximum number of links to return",
            "default": 5000
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "FirecrawlMapRequest",
        "description": "Firecrawl-compatible map request.\n\nMaps to Firecrawl's POST /map endpoint format."
      },
      "FirecrawlMapResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "default": true
          },
          "links": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Links",
            "description": "Discovered URLs"
          },
          "alterlab": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alterlab",
            "description": "AlterLab-specific metadata (credits used, map_id, etc.)"
          }
        },
        "type": "object",
        "title": "FirecrawlMapResponse",
        "description": "Firecrawl-compatible map response."
      },
      "FirecrawlMetadata": {
        "properties": {
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language"
          },
          "sourceURL": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sourceurl"
          },
          "statusCode": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Statuscode"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "ogTitle": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ogtitle"
          },
          "ogDescription": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ogdescription"
          },
          "ogImage": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ogimage"
          },
          "ogUrl": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ogurl"
          },
          "siteName": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Sitename"
          },
          "favicon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Favicon"
          },
          "robots": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Robots"
          },
          "canonical": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Canonical"
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author"
          },
          "publishedTime": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Publishedtime"
          },
          "modifiedTime": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Modifiedtime"
          }
        },
        "type": "object",
        "title": "FirecrawlMetadata",
        "description": "Metadata returned in Firecrawl response."
      },
      "FirecrawlScrapeData": {
        "properties": {
          "markdown": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Markdown"
          },
          "html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Html"
          },
          "rawHtml": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rawhtml"
          },
          "links": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Links"
          },
          "screenshot": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Screenshot"
          },
          "extract": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extract"
          },
          "metadata": {
            "$ref": "#/components/schemas/FirecrawlMetadata"
          }
        },
        "type": "object",
        "title": "FirecrawlScrapeData",
        "description": "Data object in Firecrawl response."
      },
      "FirecrawlScrapeRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "The URL to scrape"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "markdown",
                    "html",
                    "rawHtml",
                    "links",
                    "screenshot",
                    "extract",
                    "json"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats to return",
            "default": [
              "markdown"
            ]
          },
          "onlyMainContent": {
            "type": "boolean",
            "title": "Onlymaincontent",
            "description": "Only return the main content of the page excluding headers, navs, footers, etc.",
            "default": true
          },
          "includeTags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Includetags",
            "description": "Tags to include in the output"
          },
          "excludeTags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Excludetags",
            "description": "Tags to exclude from the output"
          },
          "waitFor": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Waitfor",
            "description": "Wait time in milliseconds before fetching content",
            "default": 0
          },
          "timeout": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Timeout",
            "description": "Timeout in milliseconds for the request",
            "default": 30000
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Custom headers to send with the request"
          },
          "mobile": {
            "type": "boolean",
            "title": "Mobile",
            "description": "Emulate mobile device",
            "default": false
          },
          "skipTlsVerification": {
            "type": "boolean",
            "title": "Skiptlsverification",
            "description": "Skip TLS certificate verification",
            "default": false
          },
          "removeBase64Images": {
            "type": "boolean",
            "title": "Removebase64Images",
            "description": "Remove base64 encoded images from output",
            "default": true
          },
          "proxy": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "basic",
                  "stealth",
                  "auto"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy",
            "description": "Proxy mode to use"
          },
          "storeInCache": {
            "type": "boolean",
            "title": "Storeincache",
            "description": "Store result in cache",
            "default": true
          },
          "maxAge": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Maxage",
            "description": "Maximum cache age in milliseconds"
          },
          "extract": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extract",
            "description": "Schema for structured data extraction"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "FirecrawlScrapeRequest",
        "description": "Firecrawl-compatible scrape request.\n\nMaps to Firecrawl's POST /scrape endpoint format."
      },
      "FirecrawlScrapeResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success",
            "default": true
          },
          "data": {
            "$ref": "#/components/schemas/FirecrawlScrapeData"
          },
          "alterlab": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alterlab",
            "description": "AlterLab-specific metadata (tier used, billing, etc.)"
          }
        },
        "type": "object",
        "title": "FirecrawlScrapeResponse",
        "description": "Firecrawl-compatible scrape response.\n\nMatches Firecrawl's response format for easy migration."
      },
      "ForgotPasswordRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "ForgotPasswordRequest",
        "description": "Forgot password request."
      },
      "ForgotPasswordResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "ForgotPasswordResponse",
        "description": "Forgot password response."
      },
      "ForkTemplateResponse": {
        "properties": {
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "template_id": {
            "type": "string",
            "format": "uuid",
            "title": "Template Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "workflow_id",
          "template_id",
          "name",
          "message"
        ],
        "title": "ForkTemplateResponse",
        "description": "Response after forking a template."
      },
      "GCSOutputConfig": {
        "properties": {
          "type": {
            "type": "string",
            "const": "gcs",
            "title": "Type"
          },
          "bucket": {
            "type": "string",
            "title": "Bucket",
            "description": "GCS bucket name"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix",
            "description": "Object prefix for output files",
            "default": ""
          },
          "credentials": {
            "$ref": "#/components/schemas/GCSOutputCredentials"
          },
          "format": {
            "type": "string",
            "enum": [
              "jsonl",
              "json_per_page",
              "csv"
            ],
            "title": "Format",
            "description": "Output file format",
            "default": "jsonl"
          }
        },
        "type": "object",
        "required": [
          "type",
          "bucket",
          "credentials"
        ],
        "title": "GCSOutputConfig",
        "description": "GCS output connector configuration."
      },
      "GCSOutputCredentials": {
        "properties": {
          "service_account_json": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "additionalProperties": true,
                "type": "object"
              }
            ],
            "title": "Service Account Json",
            "description": "GCS service account JSON (string or parsed object)"
          }
        },
        "type": "object",
        "required": [
          "service_account_json"
        ],
        "title": "GCSOutputCredentials",
        "description": "GCS credentials for direct export."
      },
      "GDPRConsentRequest": {
        "properties": {
          "consent": {
            "type": "boolean",
            "title": "Consent",
            "description": "Explicit consent to process session cookie data. Must be true to create sessions."
          }
        },
        "type": "object",
        "required": [
          "consent"
        ],
        "title": "GDPRConsentRequest",
        "description": "Request to record GDPR consent for session data processing."
      },
      "GDPRConsentResponse": {
        "properties": {
          "consent_given_at": {
            "type": "string",
            "format": "date-time",
            "title": "Consent Given At"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "consent_given_at",
          "message"
        ],
        "title": "GDPRConsentResponse",
        "description": "Response confirming consent has been recorded."
      },
      "GDPRDeletionResponse": {
        "properties": {
          "sessions_deleted": {
            "type": "integer",
            "title": "Sessions Deleted"
          },
          "audit_entries_redacted": {
            "type": "integer",
            "title": "Audit Entries Redacted"
          },
          "redis_keys_purged": {
            "type": "integer",
            "title": "Redis Keys Purged"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time",
            "title": "Completed At"
          }
        },
        "type": "object",
        "required": [
          "sessions_deleted",
          "audit_entries_redacted",
          "redis_keys_purged",
          "completed_at"
        ],
        "title": "GDPRDeletionResponse",
        "description": "Response after a GDPR right-to-deletion request."
      },
      "GdprTicketDeleteResponse": {
        "properties": {
          "ticket_id": {
            "type": "string",
            "title": "Ticket Id"
          },
          "ticket_ref": {
            "type": "string",
            "title": "Ticket Ref"
          },
          "deleted": {
            "type": "boolean",
            "title": "Deleted"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "ticket_id",
          "ticket_ref",
          "deleted",
          "message"
        ],
        "title": "GdprTicketDeleteResponse",
        "description": "Response after user-initiated GDPR ticket deletion."
      },
      "GeoDistributionItem": {
        "properties": {
          "region": {
            "type": "string",
            "title": "Region"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "percentage": {
            "type": "number",
            "title": "Percentage"
          }
        },
        "type": "object",
        "required": [
          "region",
          "requests",
          "percentage"
        ],
        "title": "GeoDistributionItem",
        "description": "Geographic distribution data item."
      },
      "GeoDistributionResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/GeoDistributionItem"
            },
            "type": "array",
            "title": "Data"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          }
        },
        "type": "object",
        "required": [
          "data",
          "total_requests"
        ],
        "title": "GeoDistributionResponse",
        "description": "Geographic distribution response."
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "HourlyPatternItem": {
        "properties": {
          "hour": {
            "type": "integer",
            "title": "Hour"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "avg_latency_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Latency Ms"
          }
        },
        "type": "object",
        "required": [
          "hour",
          "requests"
        ],
        "title": "HourlyPatternItem",
        "description": "Hourly pattern data item."
      },
      "HourlyPatternsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/HourlyPatternItem"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "HourlyPatternsResponse",
        "description": "Hourly patterns response."
      },
      "ImageResultResponse": {
        "properties": {
          "image_url": {
            "type": "string",
            "title": "Image Url",
            "description": "Image URL or thumbnail URL"
          },
          "alt_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alt Text",
            "description": "Alt text"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Source page URL"
          }
        },
        "type": "object",
        "required": [
          "image_url"
        ],
        "title": "ImageResultResponse",
        "description": "An image result from the image carousel."
      },
      "InfiniteScrollAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "infinite_scroll",
            "title": "Type",
            "default": "infinite_scroll"
          },
          "max_scrolls": {
            "type": "integer",
            "maximum": 50.0,
            "minimum": 1.0,
            "title": "Max Scrolls",
            "description": "Maximum scroll iterations",
            "default": 10
          },
          "delay": {
            "type": "integer",
            "maximum": 5000.0,
            "minimum": 200.0,
            "title": "Delay",
            "description": "Delay between scrolls in ms",
            "default": 1000
          },
          "end_selector": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "End Selector",
            "description": "CSS selector that indicates end of content (stops scrolling when found)"
          }
        },
        "type": "object",
        "title": "InfiniteScrollAction",
        "description": "Scroll repeatedly until end-of-content or max scrolls reached."
      },
      "InitiateLinkRequest": {
        "properties": {
          "provider": {
            "type": "string",
            "title": "Provider"
          }
        },
        "type": "object",
        "required": [
          "provider"
        ],
        "title": "InitiateLinkRequest",
        "description": "Request to initiate OAuth account linking."
      },
      "InitiateLinkResponse": {
        "properties": {
          "auth_url": {
            "type": "string",
            "title": "Auth Url"
          },
          "state": {
            "type": "string",
            "title": "State"
          }
        },
        "type": "object",
        "required": [
          "auth_url",
          "state"
        ],
        "title": "InitiateLinkResponse",
        "description": "Response with OAuth linking URL."
      },
      "InitiateSignUpRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "password": {
            "type": "string",
            "title": "Password"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "device_fingerprint": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeviceFingerprint"
              },
              {
                "type": "null"
              }
            ]
          },
          "attribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AttributionData"
              },
              {
                "type": "null"
              }
            ]
          },
          "referral_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Referral Code"
          }
        },
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "title": "InitiateSignUpRequest",
        "description": "Request to initiate signup - stores pending signup in Redis."
      },
      "InitiateSignUpResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "expires_in_minutes": {
            "type": "integer",
            "title": "Expires In Minutes"
          }
        },
        "type": "object",
        "required": [
          "message",
          "email",
          "expires_in_minutes"
        ],
        "title": "InitiateSignUpResponse",
        "description": "Response after initiating signup."
      },
      "InvitationAcceptResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          },
          "organization": {
            "$ref": "#/components/schemas/OrganizationWithRole"
          }
        },
        "type": "object",
        "required": [
          "message",
          "organization"
        ],
        "title": "InvitationAcceptResponse",
        "description": "Response after accepting an invitation."
      },
      "InvitationCreate": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "role": {
            "$ref": "#/components/schemas/OrgRole",
            "default": "member"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "InvitationCreate",
        "description": "Create invitation request."
      },
      "InvitationPublicResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "organization_name": {
            "type": "string",
            "title": "Organization Name"
          },
          "organization_avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Avatar Url"
          },
          "role": {
            "$ref": "#/components/schemas/OrgRole"
          },
          "invited_by_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invited By Name"
          },
          "invited_by_email": {
            "type": "string",
            "title": "Invited By Email"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At"
          },
          "is_expired": {
            "type": "boolean",
            "title": "Is Expired"
          }
        },
        "type": "object",
        "required": [
          "id",
          "organization_name",
          "role",
          "invited_by_email",
          "expires_at",
          "is_expired"
        ],
        "title": "InvitationPublicResponse",
        "description": "Public invitation details (for accept/decline page)."
      },
      "InvitationResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "organization_name": {
            "type": "string",
            "title": "Organization Name"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "role": {
            "$ref": "#/components/schemas/OrgRole"
          },
          "invited_by": {
            "$ref": "#/components/schemas/MemberUser"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "is_pending": {
            "type": "boolean",
            "title": "Is Pending"
          },
          "is_expired": {
            "type": "boolean",
            "title": "Is Expired"
          }
        },
        "type": "object",
        "required": [
          "id",
          "organization_id",
          "organization_name",
          "email",
          "role",
          "invited_by",
          "expires_at",
          "created_at",
          "is_pending",
          "is_expired"
        ],
        "title": "InvitationResponse",
        "description": "Invitation response."
      },
      "JobDetailResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "mode": {
            "type": "string",
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration Ms"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status Code"
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Type"
          },
          "content_length": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Length"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "error_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Code"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached",
            "default": false
          },
          "proxy_used": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Used"
          },
          "js_rendered": {
            "type": "boolean",
            "title": "Js Rendered",
            "default": false
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "webhook_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Status"
          },
          "webhook_attempts": {
            "type": "integer",
            "title": "Webhook Attempts",
            "default": 0
          },
          "request_options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Options"
          },
          "result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Result"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "mode",
          "status",
          "credits_used",
          "created_at"
        ],
        "title": "JobDetailResponse",
        "description": "Full job detail response including result."
      },
      "JobsListResponse": {
        "properties": {
          "jobs": {
            "items": {
              "$ref": "#/components/schemas/DetailedJobResponse"
            },
            "type": "array",
            "title": "Jobs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "offset": {
            "type": "integer",
            "title": "Offset"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More"
          }
        },
        "type": "object",
        "required": [
          "jobs",
          "total",
          "limit",
          "offset",
          "has_more"
        ],
        "title": "JobsListResponse",
        "description": "Paginated jobs list response."
      },
      "KBArticleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "view_count": {
            "type": "integer",
            "title": "View Count"
          },
          "helpful_count": {
            "type": "integer",
            "title": "Helpful Count"
          },
          "is_published": {
            "type": "boolean",
            "title": "Is Published"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "title",
          "slug",
          "body",
          "category",
          "tags",
          "view_count",
          "helpful_count",
          "is_published",
          "created_at",
          "updated_at"
        ],
        "title": "KBArticleResponse",
        "description": "Full KB article representation returned from the API."
      },
      "KBHelpfulRequest": {
        "properties": {
          "helpful": {
            "type": "boolean",
            "title": "Helpful",
            "description": "True = helpful, False = not helpful"
          }
        },
        "type": "object",
        "required": [
          "helpful"
        ],
        "title": "KBHelpfulRequest",
        "description": "Payload for recording whether an article was helpful."
      },
      "KBSearchResponse": {
        "properties": {
          "query": {
            "type": "string",
            "title": "Query"
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/KBSearchResult"
            },
            "type": "array",
            "title": "Results"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "query",
          "results",
          "total"
        ],
        "title": "KBSearchResponse",
        "description": "Response for the public KB search endpoint."
      },
      "KBSearchResult": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "view_count": {
            "type": "integer",
            "title": "View Count"
          },
          "helpful_count": {
            "type": "integer",
            "title": "Helpful Count"
          },
          "rank": {
            "type": "number",
            "title": "Rank",
            "description": "ts_rank score — higher means more relevant to the query",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "id",
          "title",
          "slug",
          "body",
          "category",
          "tags",
          "view_count",
          "helpful_count"
        ],
        "title": "KBSearchResult",
        "description": "Single search hit in a KB search response."
      },
      "KeySpendLimitResponse": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "api_key_name": {
            "type": "string",
            "title": "Api Key Name"
          },
          "limits": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SpendLimitStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "has_limits": {
            "type": "boolean",
            "title": "Has Limits",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "api_key_name"
        ],
        "title": "KeySpendLimitResponse",
        "description": "Response for per-key limit status."
      },
      "KeyUsageByPeriod": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "requests": {
            "type": "integer",
            "title": "Requests",
            "default": 0
          },
          "spend_microcents": {
            "type": "integer",
            "title": "Spend Microcents",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "date"
        ],
        "title": "KeyUsageByPeriod",
        "description": "Usage broken down by time period."
      },
      "KeyUsageSummary": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "api_key_name": {
            "type": "string",
            "title": "Api Key Name"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests",
            "default": 0
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests",
            "default": 0
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests",
            "default": 0
          },
          "total_spend_microcents": {
            "type": "integer",
            "title": "Total Spend Microcents",
            "default": 0
          },
          "top_domains": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "title": "Top Domains"
          },
          "period_start": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period Start"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "api_key_name"
        ],
        "title": "KeyUsageSummary",
        "description": "Per-key usage summary for the current period."
      },
      "KeyUsageTimeseriesResponse": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "days": {
            "type": "integer",
            "title": "Days"
          },
          "granularity": {
            "type": "string",
            "title": "Granularity",
            "default": "day"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/KeyUsageByPeriod"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "days",
          "data"
        ],
        "title": "KeyUsageTimeseriesResponse",
        "description": "Response for per-key usage timeseries."
      },
      "KillAllResponse": {
        "properties": {
          "deactivated_count": {
            "type": "integer",
            "title": "Deactivated Count",
            "description": "Number of sessions deactivated"
          },
          "deactivated_session_ids": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Deactivated Session Ids",
            "description": "IDs of deactivated sessions"
          },
          "propagated": {
            "type": "boolean",
            "title": "Propagated",
            "description": "Whether invalidation was propagated to workers"
          }
        },
        "type": "object",
        "required": [
          "deactivated_count",
          "deactivated_session_ids",
          "propagated"
        ],
        "title": "KillAllResponse",
        "description": "Response for emergency kill-all endpoint."
      },
      "KnowledgePanelResponse": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Entity name"
          },
          "entity_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Entity Type",
            "description": "Entity type (e.g. 'Company', 'Person')"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Entity description"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Source attribution (e.g. 'Wikipedia')"
          },
          "facts": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Facts",
            "description": "Key-value fact pairs"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image Url",
            "description": "Entity image URL"
          }
        },
        "type": "object",
        "required": [
          "title"
        ],
        "title": "KnowledgePanelResponse",
        "description": "Knowledge panel / entity card shown alongside search results."
      },
      "LegacyKeysStatusResponse": {
        "properties": {
          "has_legacy_keys": {
            "type": "boolean",
            "title": "Has Legacy Keys"
          },
          "legacy_key_count": {
            "type": "integer",
            "title": "Legacy Key Count"
          },
          "notice_shown": {
            "type": "boolean",
            "title": "Notice Shown"
          }
        },
        "type": "object",
        "required": [
          "has_legacy_keys",
          "legacy_key_count",
          "notice_shown"
        ],
        "title": "LegacyKeysStatusResponse",
        "description": "Response for legacy API key status check."
      },
      "LinkedAccountResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          },
          "provider_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider Email"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "linked_at": {
            "type": "string",
            "format": "date-time",
            "title": "Linked At"
          },
          "is_primary": {
            "type": "boolean",
            "title": "Is Primary"
          }
        },
        "type": "object",
        "required": [
          "id",
          "provider",
          "provider_email",
          "display_name",
          "avatar_url",
          "linked_at",
          "is_primary"
        ],
        "title": "LinkedAccountResponse",
        "description": "Response model for a linked account."
      },
      "LinkedAccountsListResponse": {
        "properties": {
          "accounts": {
            "items": {
              "$ref": "#/components/schemas/LinkedAccountResponse"
            },
            "type": "array",
            "title": "Accounts"
          },
          "primary_method": {
            "type": "string",
            "title": "Primary Method"
          },
          "has_password": {
            "type": "boolean",
            "title": "Has Password"
          }
        },
        "type": "object",
        "required": [
          "accounts",
          "primary_method",
          "has_password"
        ],
        "title": "LinkedAccountsListResponse",
        "description": "Response model for list of linked accounts."
      },
      "LocalResultResponse": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Business name"
          },
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address",
            "description": "Business address"
          },
          "rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating",
            "description": "Star rating (1-5)"
          },
          "review_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Count",
            "description": "Number of reviews"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone",
            "description": "Phone number"
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category",
            "description": "Business category"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "LocalResultResponse",
        "description": "A local pack result (business listing from Google Maps / Local Pack)."
      },
      "Location": {
        "properties": {
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code (e.g., 'DE', 'JP', 'BR'). Routes request through a proxy in the specified country."
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "ISO 639-1 language code (e.g., 'de', 'ja', 'pt'). Sets the Accept-Language header and browser locale."
          }
        },
        "type": "object",
        "title": "Location",
        "description": "Geo-targeting parameters for localized content scraping.\n\nControls proxy country routing, Accept-Language header, and browser locale\nto retrieve content as seen from a specific geographic location."
      },
      "LoginHistoryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Failure Reason"
          }
        },
        "type": "object",
        "required": [
          "id",
          "created_at",
          "ip_address",
          "user_agent",
          "country",
          "city",
          "success",
          "failure_reason"
        ],
        "title": "LoginHistoryResponse",
        "description": "Login history response."
      },
      "LoginRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "password": {
            "type": "string",
            "title": "Password"
          }
        },
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "title": "LoginRequest"
      },
      "MapComparisonResponse": {
        "properties": {
          "map_id_a": {
            "type": "string",
            "title": "Map Id A",
            "description": "Older map identifier (baseline)"
          },
          "map_id_b": {
            "type": "string",
            "title": "Map Id B",
            "description": "Newer map identifier (comparison target)"
          },
          "domain": {
            "type": "string",
            "title": "Domain",
            "description": "Domain both maps belong to"
          },
          "created_at_a": {
            "type": "string",
            "format": "date-time",
            "title": "Created At A",
            "description": "When map A was captured"
          },
          "created_at_b": {
            "type": "string",
            "format": "date-time",
            "title": "Created At B",
            "description": "When map B was captured"
          },
          "summary": {
            "$ref": "#/components/schemas/MapComparisonSummary",
            "description": "Aggregate change counts"
          },
          "added_urls": {
            "items": {
              "$ref": "#/components/schemas/MapComparisonURLEntry"
            },
            "type": "array",
            "title": "Added Urls",
            "description": "URLs found in map B but not map A"
          },
          "removed_urls": {
            "items": {
              "$ref": "#/components/schemas/MapComparisonURLEntry"
            },
            "type": "array",
            "title": "Removed Urls",
            "description": "URLs found in map A but not map B"
          },
          "changed_urls": {
            "items": {
              "$ref": "#/components/schemas/MapComparisonURLEntry"
            },
            "type": "array",
            "title": "Changed Urls",
            "description": "URLs found in both maps but with different title or description"
          },
          "unchanged_urls": {
            "items": {
              "$ref": "#/components/schemas/MapComparisonURLEntry"
            },
            "type": "array",
            "title": "Unchanged Urls",
            "description": "URLs found in both maps with identical metadata"
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Maximum URL entries returned per category"
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Number of entries skipped per category"
          },
          "total_added": {
            "type": "integer",
            "title": "Total Added",
            "description": "Total added URLs (unpaged)"
          },
          "total_removed": {
            "type": "integer",
            "title": "Total Removed",
            "description": "Total removed URLs (unpaged)"
          },
          "total_changed": {
            "type": "integer",
            "title": "Total Changed",
            "description": "Total changed URLs (unpaged)"
          },
          "total_unchanged": {
            "type": "integer",
            "title": "Total Unchanged",
            "description": "Total unchanged URLs (unpaged)"
          }
        },
        "type": "object",
        "required": [
          "map_id_a",
          "map_id_b",
          "domain",
          "created_at_a",
          "created_at_b",
          "summary",
          "added_urls",
          "removed_urls",
          "unchanged_urls",
          "limit",
          "offset",
          "total_added",
          "total_removed",
          "total_changed",
          "total_unchanged"
        ],
        "title": "MapComparisonResponse",
        "description": "Full comparison result between two map snapshots."
      },
      "MapComparisonSummary": {
        "properties": {
          "added": {
            "type": "integer",
            "title": "Added",
            "description": "URLs present in map B but not in map A"
          },
          "removed": {
            "type": "integer",
            "title": "Removed",
            "description": "URLs present in map A but not in map B"
          },
          "changed": {
            "type": "integer",
            "title": "Changed",
            "description": "URLs present in both maps but with different title or description",
            "default": 0
          },
          "unchanged": {
            "type": "integer",
            "title": "Unchanged",
            "description": "URLs present in both maps with identical metadata"
          },
          "total_a": {
            "type": "integer",
            "title": "Total A",
            "description": "Total URLs in map A"
          },
          "total_b": {
            "type": "integer",
            "title": "Total B",
            "description": "Total URLs in map B"
          },
          "sitemap_changed": {
            "type": "boolean",
            "title": "Sitemap Changed",
            "description": "Whether sitemap discovery status differs between maps"
          },
          "url_delta": {
            "type": "integer",
            "title": "Url Delta",
            "description": "Net change in URL count (total_b - total_a; positive = growth)"
          }
        },
        "type": "object",
        "required": [
          "added",
          "removed",
          "unchanged",
          "total_a",
          "total_b",
          "sitemap_changed",
          "url_delta"
        ],
        "title": "MapComparisonSummary",
        "description": "Aggregate counts of structural changes between two maps."
      },
      "MapComparisonURLEntry": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url",
            "description": "The URL"
          },
          "source_a": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "sitemap",
                  "link",
                  "start"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Source A",
            "description": "Discovery source in map A"
          },
          "source_b": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "sitemap",
                  "link",
                  "start"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Source B",
            "description": "Discovery source in map B"
          },
          "depth_a": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth A",
            "description": "Depth in map A"
          },
          "depth_b": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Depth B",
            "description": "Depth in map B"
          },
          "title_a": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title A",
            "description": "Page title in map A"
          },
          "title_b": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title B",
            "description": "Page title in map B"
          },
          "description_a": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description A",
            "description": "Meta description in map A"
          },
          "description_b": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description B",
            "description": "Meta description in map B"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "MapComparisonURLEntry",
        "description": "A URL that appears in a comparison diff."
      },
      "MapDetailResponse": {
        "properties": {
          "map_id": {
            "type": "string",
            "title": "Map Id",
            "description": "Unique identifier for this map operation"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Starting URL that was mapped"
          },
          "domain": {
            "type": "string",
            "title": "Domain",
            "description": "Domain that was mapped"
          },
          "total_urls": {
            "type": "integer",
            "title": "Total Urls",
            "description": "Number of URLs discovered"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits consumed"
          },
          "sitemap_found": {
            "type": "boolean",
            "title": "Sitemap Found",
            "description": "Whether a sitemap was successfully parsed"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the map was executed"
          },
          "urls": {
            "items": {
              "$ref": "#/components/schemas/MapURLEntry"
            },
            "type": "array",
            "title": "Urls",
            "description": "Discovered URLs with metadata"
          },
          "config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config",
            "description": "Map configuration used"
          }
        },
        "type": "object",
        "required": [
          "map_id",
          "url",
          "domain",
          "total_urls",
          "credits_used",
          "sitemap_found",
          "created_at",
          "urls"
        ],
        "title": "MapDetailResponse",
        "description": "Full map result including discovered URLs."
      },
      "MapHistoryItem": {
        "properties": {
          "map_id": {
            "type": "string",
            "title": "Map Id",
            "description": "Unique identifier for this map operation"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Starting URL that was mapped"
          },
          "domain": {
            "type": "string",
            "title": "Domain",
            "description": "Domain that was mapped"
          },
          "total_urls": {
            "type": "integer",
            "title": "Total Urls",
            "description": "Number of URLs discovered"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits consumed"
          },
          "sitemap_found": {
            "type": "boolean",
            "title": "Sitemap Found",
            "description": "Whether a sitemap was successfully parsed"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the map was executed"
          }
        },
        "type": "object",
        "required": [
          "map_id",
          "url",
          "domain",
          "total_urls",
          "credits_used",
          "sitemap_found",
          "created_at"
        ],
        "title": "MapHistoryItem",
        "description": "A single map history entry (used in list and detail responses)."
      },
      "MapListResponse": {
        "properties": {
          "maps": {
            "items": {
              "$ref": "#/components/schemas/MapHistoryItem"
            },
            "type": "array",
            "title": "Maps",
            "description": "Map history entries"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of maps for this user"
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Maximum items per page"
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Number of items skipped"
          }
        },
        "type": "object",
        "required": [
          "maps",
          "total",
          "limit",
          "offset"
        ],
        "title": "MapListResponse",
        "description": "Paginated list of user's map history."
      },
      "MapRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "Starting URL for site discovery"
          },
          "max_pages": {
            "type": "integer",
            "maximum": 50000.0,
            "minimum": 1.0,
            "title": "Max Pages",
            "description": "Maximum URLs to discover",
            "default": 500
          },
          "max_depth": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Max Depth",
            "description": "Link-following depth (0 = start page + sitemap only)",
            "default": 3
          },
          "include_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Include Patterns",
            "description": "Glob patterns — only include URLs whose path matches at least one"
          },
          "exclude_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclude Patterns",
            "description": "Glob patterns — exclude URLs whose path matches any"
          },
          "search": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Search",
            "description": "Query to filter/rank discovered URLs by relevance"
          },
          "sitemap": {
            "type": "string",
            "enum": [
              "skip",
              "include",
              "only"
            ],
            "title": "Sitemap",
            "description": "\"skip\" = ignore sitemaps, \"include\" = parse sitemaps + follow links (default), \"only\" = return only sitemap URLs without link following",
            "default": "include"
          },
          "sitemap_path": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Sitemap Path",
            "description": "Custom sitemap location (e.g., /custom-sitemap.xml)"
          },
          "include_metadata": {
            "type": "boolean",
            "title": "Include Metadata",
            "description": "Fetch title and meta description for each URL via lightweight GET",
            "default": false
          },
          "include_subdomains": {
            "type": "boolean",
            "title": "Include Subdomains",
            "description": "Include URLs from subdomains of the target domain",
            "default": false
          },
          "respect_robots": {
            "type": "boolean",
            "title": "Respect Robots",
            "description": "Respect robots.txt directives",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "MapRequest",
        "description": "Request body for POST /v1/map."
      },
      "MapResponse": {
        "properties": {
          "map_id": {
            "type": "string",
            "title": "Map Id",
            "description": "Unique identifier for this map operation"
          },
          "total_urls": {
            "type": "integer",
            "title": "Total Urls",
            "description": "Total number of URLs discovered"
          },
          "urls": {
            "items": {
              "$ref": "#/components/schemas/MapURLEntry"
            },
            "type": "array",
            "title": "Urls",
            "description": "Discovered URLs with metadata"
          },
          "sitemap_found": {
            "type": "boolean",
            "title": "Sitemap Found",
            "description": "Whether a sitemap was successfully parsed"
          },
          "robots_txt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RobotsTxtInfo"
              },
              {
                "type": "null"
              }
            ],
            "description": "robots.txt summary for the domain"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits consumed by this map call"
          }
        },
        "type": "object",
        "required": [
          "map_id",
          "total_urls",
          "urls",
          "sitemap_found",
          "credits_used"
        ],
        "title": "MapResponse",
        "description": "Response for POST /v1/map."
      },
      "MapScheduleCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron",
            "description": "Cron expression (5 fields), e.g. '0 6 * * 1'"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "map_config": {
            "$ref": "#/components/schemas/MapScheduleMapConfig"
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs",
            "description": "Maximum number of runs before the schedule auto-disables"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "name",
          "cron",
          "map_config"
        ],
        "title": "MapScheduleCreateRequest",
        "description": "Create a new map schedule."
      },
      "MapScheduleListResponse": {
        "properties": {
          "schedules": {
            "items": {
              "$ref": "#/components/schemas/MapScheduleResponse"
            },
            "type": "array",
            "title": "Schedules"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "schedules",
          "total"
        ],
        "title": "MapScheduleListResponse",
        "description": "Paginated list of map schedules."
      },
      "MapScheduleMapConfig": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "Starting URL for site discovery"
          },
          "max_pages": {
            "type": "integer",
            "maximum": 50000.0,
            "minimum": 1.0,
            "title": "Max Pages",
            "default": 500
          },
          "max_depth": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 0.0,
            "title": "Max Depth",
            "default": 3
          },
          "include_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Include Patterns"
          },
          "exclude_patterns": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclude Patterns"
          },
          "search": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Search"
          },
          "sitemap": {
            "type": "string",
            "enum": [
              "skip",
              "include",
              "only"
            ],
            "title": "Sitemap",
            "default": "include"
          },
          "sitemap_path": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Sitemap Path"
          },
          "include_metadata": {
            "type": "boolean",
            "title": "Include Metadata",
            "default": false
          },
          "include_subdomains": {
            "type": "boolean",
            "title": "Include Subdomains",
            "default": false
          },
          "respect_robots": {
            "type": "boolean",
            "title": "Respect Robots",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "MapScheduleMapConfig",
        "description": "Frozen map configuration executed on each scheduled run.\n\nMirrors the essential fields of MapRequest but stored as a JSON blob\nso the schedule is self-contained (no user input at execution time)."
      },
      "MapScheduleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "map_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Map Config"
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "next_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Run At"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "cron",
          "timezone",
          "map_config",
          "is_active",
          "run_count",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "MapScheduleResponse",
        "description": "Map schedule detail response."
      },
      "MapScheduleRunListResponse": {
        "properties": {
          "runs": {
            "items": {
              "$ref": "#/components/schemas/MapScheduleRunResponse"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "runs",
          "total"
        ],
        "title": "MapScheduleRunListResponse",
        "description": "Paginated list of map schedule runs."
      },
      "MapScheduleRunResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "map_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Map Id"
          },
          "urls_discovered": {
            "type": "integer",
            "title": "Urls Discovered"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "status",
          "urls_discovered",
          "credits_used",
          "created_at"
        ],
        "title": "MapScheduleRunResponse",
        "description": "Execution record for a scheduled map run."
      },
      "MapScheduleUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "cron": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "map_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MapScheduleMapConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "max_runs": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Runs"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          }
        },
        "type": "object",
        "title": "MapScheduleUpdateRequest",
        "description": "Update an existing map schedule."
      },
      "MapURLEntry": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Discovered URL"
          },
          "depth": {
            "type": "integer",
            "title": "Depth",
            "description": "Depth at which URL was discovered (0 = sitemap/start page)"
          },
          "source": {
            "type": "string",
            "enum": [
              "sitemap",
              "link",
              "start"
            ],
            "title": "Source",
            "description": "How the URL was discovered"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title",
            "description": "Page title (if include_metadata=true)"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Meta description (if include_metadata=true)"
          },
          "relevance_score": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Relevance Score",
            "description": "Relevance score 0-1 (if search param provided)"
          }
        },
        "type": "object",
        "required": [
          "url",
          "depth",
          "source"
        ],
        "title": "MapURLEntry",
        "description": "A single discovered URL with optional metadata."
      },
      "MemberListResponse": {
        "properties": {
          "members": {
            "items": {
              "$ref": "#/components/schemas/OrganizationMemberResponse"
            },
            "type": "array",
            "title": "Members"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "members",
          "total"
        ],
        "title": "MemberListResponse",
        "description": "List of members response."
      },
      "MemberRoleUpdate": {
        "properties": {
          "role": {
            "$ref": "#/components/schemas/OrgRole"
          }
        },
        "type": "object",
        "required": [
          "role"
        ],
        "title": "MemberRoleUpdate",
        "description": "Update member role request."
      },
      "MemberUser": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email"
        ],
        "title": "MemberUser",
        "description": "User info for member response."
      },
      "MethodBreakdownResponse": {
        "properties": {
          "by_method": {
            "additionalProperties": {
              "type": "integer"
            },
            "propertyNames": {
              "enum": [
                "GET",
                "POST",
                "PUT",
                "PATCH",
                "DELETE",
                "HEAD"
              ]
            },
            "type": "object",
            "title": "By Method"
          },
          "api_relay_count": {
            "type": "integer",
            "title": "Api Relay Count"
          },
          "page_scrape_count": {
            "type": "integer",
            "title": "Page Scrape Count"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "window_days": {
            "type": "integer",
            "title": "Window Days"
          }
        },
        "type": "object",
        "required": [
          "by_method",
          "api_relay_count",
          "page_scrape_count",
          "total",
          "window_days"
        ],
        "title": "MethodBreakdownResponse",
        "description": "Breakdown of scrape requests by target HTTP method.\n\nDistinguishes API relay calls (POST/PUT/PATCH/DELETE) from\nstandard page scrapes (GET) for usage visibility."
      },
      "MinimalHealthResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "default": "ok"
          }
        },
        "type": "object",
        "title": "MinimalHealthResponse",
        "description": "Minimal health check response for public-facing endpoints.\n\nReturns only the service availability status without infrastructure details.\nUse /api/v1/health/detailed (admin-only) for full connectivity information."
      },
      "MonitorCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "url": {
            "type": "string",
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "URL to monitor for changes, or keyword:<term> for SERP monitors"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "check_interval": {
            "type": "string",
            "title": "Check Interval",
            "description": "Cron expression for check frequency, e.g. '0 */6 * * *' (every 6h)",
            "default": "0 */6 * * *"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "diff_mode": {
            "type": "string",
            "enum": [
              "semantic",
              "exact",
              "selector"
            ],
            "title": "Diff Mode",
            "description": "Diff algorithm: semantic (structural), exact (byte-level), selector (CSS selectors)",
            "default": "semantic"
          },
          "monitor_selectors": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 20
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Selectors",
            "description": "CSS selectors to track (required when diff_mode=selector, max 20)"
          },
          "notify_on": {
            "type": "string",
            "enum": [
              "change",
              "always"
            ],
            "title": "Notify On",
            "description": "When to fire webhook: 'change' (only on diff) or 'always' (every check)",
            "default": "change"
          },
          "options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON Schema for structured extraction on content change. When set, the worker runs LLM-based extraction after change detection and includes the result in the monitor.changed webhook payload. Only fires on change — no LLM cost on no-change checks."
          }
        },
        "type": "object",
        "required": [
          "name",
          "url"
        ],
        "title": "MonitorCreateRequest",
        "description": "Create a new monitor (schedule with change detection)."
      },
      "MonitorGroupCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "Group name. Each monitor is named '{name} — {domain}'."
          },
          "urls": {
            "items": {
              "type": "string",
              "maxLength": 2083,
              "minLength": 1,
              "format": "uri"
            },
            "type": "array",
            "maxItems": 20,
            "minItems": 1,
            "title": "Urls",
            "description": "URLs to monitor as a group (max 20). Each URL gets its own monitor."
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "check_interval": {
            "type": "string",
            "title": "Check Interval",
            "description": "Cron expression shared by all monitors in the group",
            "default": "0 */6 * * *"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "diff_mode": {
            "type": "string",
            "enum": [
              "semantic",
              "exact",
              "selector"
            ],
            "title": "Diff Mode",
            "description": "Diff algorithm applied to all monitors in the group",
            "default": "semantic"
          },
          "monitor_selectors": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 20
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Selectors",
            "description": "CSS selectors to track (required when diff_mode=selector, max 20)"
          },
          "notify_on": {
            "type": "string",
            "enum": [
              "change",
              "always"
            ],
            "title": "Notify On",
            "description": "When to fire webhook: 'change' or 'always'",
            "default": "change"
          },
          "options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL called when any monitor in the group detects a change"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON Schema applied to all monitors in the group. The worker runs LLM-based extraction after change detection."
          }
        },
        "type": "object",
        "required": [
          "name",
          "urls"
        ],
        "title": "MonitorGroupCreateRequest",
        "description": "Create a monitor group — one config applied to multiple URLs.\n\nCreates N ScrapeSchedule rows (one per URL) all sharing the same group_id.\nEach URL gets its own monitor with individual change tracking, but shares\nthe same schema, webhook, cron, and diff configuration.\n\nMax 20 URLs per group. Respects the same per-user schedule limits as\nindividual monitor creation."
      },
      "MonitorGroupListResponse": {
        "properties": {
          "groups": {
            "items": {
              "$ref": "#/components/schemas/MonitorGroupResponse"
            },
            "type": "array",
            "title": "Groups"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "groups",
          "total"
        ],
        "title": "MonitorGroupListResponse",
        "description": "List of monitor groups."
      },
      "MonitorGroupResponse": {
        "properties": {
          "group_id": {
            "type": "string",
            "format": "uuid",
            "title": "Group Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "monitor_count": {
            "type": "integer",
            "title": "Monitor Count",
            "description": "Total number of monitors in the group"
          },
          "active_count": {
            "type": "integer",
            "title": "Active Count",
            "description": "Number of active monitors in the group"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Urls",
            "description": "URLs tracked by the group"
          },
          "check_interval": {
            "type": "string",
            "title": "Check Interval"
          },
          "diff_mode": {
            "type": "string",
            "title": "Diff Mode"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "group_id",
          "name",
          "monitor_count",
          "active_count",
          "urls",
          "check_interval",
          "diff_mode",
          "created_at"
        ],
        "title": "MonitorGroupResponse",
        "description": "Response for a single monitor group — aggregate view of all monitors sharing group_id."
      },
      "MonitorListResponse": {
        "properties": {
          "monitors": {
            "items": {
              "$ref": "#/components/schemas/MonitorResponse"
            },
            "type": "array",
            "title": "Monitors"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "monitors",
          "total"
        ],
        "title": "MonitorListResponse",
        "description": "List of monitors."
      },
      "MonitorResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "check_interval": {
            "type": "string",
            "title": "Check Interval"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "diff_mode": {
            "type": "string",
            "title": "Diff Mode"
          },
          "monitor_selectors": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Selectors"
          },
          "notify_on": {
            "type": "string",
            "title": "Notify On"
          },
          "options": {
            "additionalProperties": true,
            "type": "object",
            "title": "Options",
            "default": {}
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "next_run_at": {
            "type": "string",
            "format": "date-time",
            "title": "Next Run At"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "url",
          "check_interval",
          "timezone",
          "diff_mode",
          "notify_on",
          "is_active",
          "next_run_at",
          "run_count",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "MonitorResponse",
        "description": "Monitor detail response."
      },
      "MonitorUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "url": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "check_interval": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Check Interval"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "diff_mode": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "semantic",
                  "exact",
                  "selector"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Diff Mode"
          },
          "monitor_selectors": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 20
              },
              {
                "type": "null"
              }
            ],
            "title": "Monitor Selectors"
          },
          "notify_on": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "change",
                  "always"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Notify On"
          },
          "options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "Update the JSON Schema used for extraction on change detection. Pass null to remove schema extraction from this monitor."
          }
        },
        "type": "object",
        "title": "MonitorUpdateRequest",
        "description": "Update an existing monitor. Use pause/resume endpoints to change active state."
      },
      "MrrTrendPoint": {
        "properties": {
          "month": {
            "type": "string",
            "title": "Month"
          },
          "mrr_cents": {
            "type": "integer",
            "title": "Mrr Cents"
          }
        },
        "type": "object",
        "required": [
          "month",
          "mrr_cents"
        ],
        "title": "MrrTrendPoint",
        "description": "One month of MRR trend data."
      },
      "NewsResultResponse": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "News headline"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Article URL"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Publisher name"
          },
          "date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date",
            "description": "Publication date"
          },
          "thumbnail_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thumbnail Url",
            "description": "Thumbnail URL"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "NewsResultResponse",
        "description": "A news result from the top stories / news carousel."
      },
      "NextTierInfo": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "floor_cents": {
            "type": "integer",
            "title": "Floor Cents"
          },
          "requests_per_minute": {
            "type": "integer",
            "title": "Requests Per Minute"
          },
          "concurrent_requests": {
            "type": "integer",
            "title": "Concurrent Requests"
          },
          "deposit_needed_cents": {
            "type": "integer",
            "title": "Deposit Needed Cents"
          }
        },
        "type": "object",
        "required": [
          "name",
          "slug",
          "floor_cents",
          "requests_per_minute",
          "concurrent_requests",
          "deposit_needed_cents"
        ],
        "title": "NextTierInfo",
        "description": "Information about the next balance tier."
      },
      "NodePosition": {
        "properties": {
          "x": {
            "type": "number",
            "title": "X",
            "default": 0
          },
          "y": {
            "type": "number",
            "title": "Y",
            "default": 0
          }
        },
        "type": "object",
        "title": "NodePosition",
        "description": "Visual position of a node on the canvas."
      },
      "NotificationHistoryListResponse": {
        "properties": {
          "notifications": {
            "items": {
              "$ref": "#/components/schemas/NotificationHistoryResponse"
            },
            "type": "array",
            "title": "Notifications"
          }
        },
        "type": "object",
        "required": [
          "notifications"
        ],
        "title": "NotificationHistoryListResponse"
      },
      "NotificationHistoryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "type": {
            "type": "string",
            "title": "Type"
          },
          "variant": {
            "type": "string",
            "title": "Variant"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "action_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action Url"
          },
          "action_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action Label"
          },
          "dismiss_delay": {
            "type": "integer",
            "title": "Dismiss Delay"
          },
          "priority": {
            "type": "integer",
            "title": "Priority"
          },
          "is_dismissed": {
            "type": "boolean",
            "title": "Is Dismissed",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "id",
          "type",
          "variant",
          "title",
          "body",
          "dismiss_delay",
          "priority"
        ],
        "title": "NotificationHistoryResponse",
        "description": "Notification with dismissal status for history view."
      },
      "NotificationPrefItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "title": "Tenant Id"
          },
          "event_type": {
            "type": "string",
            "title": "Event Type"
          },
          "channel": {
            "type": "string",
            "title": "Channel"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "tenant_id",
          "event_type",
          "channel",
          "enabled",
          "created_at",
          "updated_at"
        ],
        "title": "NotificationPrefItem",
        "description": "Single notification preference row (read)."
      },
      "NotificationPrefListResponse": {
        "properties": {
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "title": "Tenant Id"
          },
          "prefs": {
            "items": {
              "$ref": "#/components/schemas/NotificationPrefItem"
            },
            "type": "array",
            "title": "Prefs"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Number of preference rows returned"
          }
        },
        "type": "object",
        "required": [
          "tenant_id",
          "prefs",
          "total"
        ],
        "title": "NotificationPrefListResponse",
        "description": "Response for GET .../notification-prefs — full list of prefs for a tenant."
      },
      "NotificationPrefPatchItem": {
        "properties": {
          "event_type": {
            "type": "string",
            "enum": [
              "delivery.failed",
              "batch.completed",
              "usage.threshold"
            ],
            "title": "Event Type",
            "description": "Event type to configure."
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "webhook",
              "in-dashboard"
            ],
            "title": "Channel",
            "description": "Notification delivery channel to configure."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Whether to enable this (event_type, channel) combination."
          }
        },
        "type": "object",
        "required": [
          "event_type",
          "channel",
          "enabled"
        ],
        "title": "NotificationPrefPatchItem",
        "description": "Single preference update within a PATCH request body."
      },
      "NotificationPrefPatchRequest": {
        "properties": {
          "prefs": {
            "items": {
              "$ref": "#/components/schemas/NotificationPrefPatchItem"
            },
            "type": "array",
            "minItems": 1,
            "title": "Prefs",
            "description": "List of preference updates. Each item is upserted individually."
          }
        },
        "type": "object",
        "required": [
          "prefs"
        ],
        "title": "NotificationPrefPatchRequest",
        "description": "Request body for PATCH .../notification-prefs.\n\nUpserts each item in the list — existing rows are updated in-place;\nabsent (event_type, channel) combinations are inserted with the caller's\nprovided ``enabled`` value.  Rows not mentioned in the request are\nleft unchanged."
      },
      "NotificationPrefPatchResponse": {
        "properties": {
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "title": "Tenant Id"
          },
          "prefs": {
            "items": {
              "$ref": "#/components/schemas/NotificationPrefItem"
            },
            "type": "array",
            "title": "Prefs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "upserted": {
            "type": "integer",
            "title": "Upserted",
            "description": "Number of rows created or updated in this request."
          }
        },
        "type": "object",
        "required": [
          "tenant_id",
          "prefs",
          "total",
          "upserted"
        ],
        "title": "NotificationPrefPatchResponse",
        "description": "Response for PATCH .../notification-prefs — returns the full updated pref list."
      },
      "NotificationSettingsSchema": {
        "properties": {
          "email_admin_reply": {
            "type": "boolean",
            "title": "Email Admin Reply",
            "description": "Receive email when admin posts a reply to your ticket",
            "default": true
          },
          "email_status_change": {
            "type": "boolean",
            "title": "Email Status Change",
            "description": "Receive email when your ticket status changes",
            "default": true
          },
          "email_resolved": {
            "type": "boolean",
            "title": "Email Resolved",
            "description": "Receive email when your ticket is marked resolved",
            "default": true
          }
        },
        "type": "object",
        "title": "NotificationSettingsSchema",
        "description": "The three email notification toggles stored in user_support_preferences.notification_settings.\n\nAll fields default to True (opt-in by default)."
      },
      "OAuthSignInRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "provider": {
            "type": "string",
            "title": "Provider"
          },
          "provider_account_id": {
            "type": "string",
            "title": "Provider Account Id"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "device_fingerprint": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeviceFingerprint"
              },
              {
                "type": "null"
              }
            ]
          },
          "attribution": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AttributionData"
              },
              {
                "type": "null"
              }
            ]
          },
          "anonymous_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Anonymous Id"
          }
        },
        "type": "object",
        "required": [
          "email",
          "provider",
          "provider_account_id"
        ],
        "title": "OAuthSignInRequest",
        "description": "Request model for OAuth sign-in/sign-up."
      },
      "OCRHealthResponse": {
        "properties": {
          "available": {
            "type": "boolean",
            "title": "Available"
          },
          "tesseract_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tesseract Version"
          },
          "pillow_version": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pillow Version"
          },
          "languages": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Languages"
          },
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "available"
        ],
        "title": "OCRHealthResponse",
        "description": "OCR subsystem health/availability details."
      },
      "OnboardRequest": {
        "properties": {
          "country_code": {
            "type": "string",
            "maxLength": 2,
            "minLength": 2,
            "title": "Country Code",
            "description": "ISO 3166-1 alpha-2 country code (e.g. 'US', 'GB')",
            "default": "US"
          },
          "return_url": {
            "type": "string",
            "minLength": 1,
            "format": "uri",
            "title": "Return Url",
            "description": "URL Stripe redirects to after onboarding is completed"
          },
          "refresh_url": {
            "type": "string",
            "minLength": 1,
            "format": "uri",
            "title": "Refresh Url",
            "description": "URL Stripe redirects to if the onboarding link expires"
          }
        },
        "type": "object",
        "required": [
          "return_url",
          "refresh_url"
        ],
        "title": "OnboardRequest",
        "description": "POST /creator/connect/onboard request body."
      },
      "OnboardResponse": {
        "properties": {
          "onboarding_url": {
            "type": "string",
            "title": "Onboarding Url"
          },
          "stripe_account_id": {
            "type": "string",
            "title": "Stripe Account Id"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Complete identity verification on Stripe to enable payouts."
          }
        },
        "type": "object",
        "required": [
          "onboarding_url",
          "stripe_account_id"
        ],
        "title": "OnboardResponse",
        "description": "POST /creator/connect/onboard response."
      },
      "OnboardingEventRequest": {
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "completed",
              "skipped"
            ],
            "title": "Event"
          },
          "at_step": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "At Step"
          }
        },
        "type": "object",
        "required": [
          "event"
        ],
        "title": "OnboardingEventRequest",
        "description": "Payload for an onboarding lifecycle event."
      },
      "OpenRouterExchangeRequest": {
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 512,
            "minLength": 1,
            "title": "Code",
            "description": "The authorization code received from the OpenRouter OAuth callback."
          },
          "code_verifier": {
            "type": "string",
            "maxLength": 128,
            "minLength": 43,
            "title": "Code Verifier",
            "description": "The PKCE code verifier that was used to generate the code challenge."
          },
          "state": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256,
                "pattern": "^[A-Za-z0-9_-]{1,256}$"
              },
              {
                "type": "null"
              }
            ],
            "title": "State",
            "description": "The CSRF state nonce that was included in the authorization URL. Accepted here for audit logging. Must be URL-safe base64url characters only (alphanumeric, underscore, hyphen). Security rationale: server-side state validation requires storing the nonce in Redis before the popup opens and threading it through the Next.js proxy — significant plumbing for a LOW-severity gap that PKCE already closes. The frontend validates state before calling this endpoint (postMessage handler rejects messages with a mismatched nonce). PKCE code_verifier provides cryptographic proof that the code was requested by the same party, making CSRF interception of the code useless without the verifier. The endpoint also requires authenticated FlexibleUser, so an unauthenticated attacker cannot call it at all. Together these three layers (auth + PKCE + client-side state) render server-side nonce validation advisory-only."
          }
        },
        "type": "object",
        "required": [
          "code",
          "code_verifier"
        ],
        "title": "OpenRouterExchangeRequest",
        "description": "Request body for exchanging an OpenRouter OAuth PKCE code for an API key."
      },
      "OptOutRequest": {
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 320,
            "title": "Email",
            "description": "Email address to opt out"
          },
          "domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain",
            "description": "Optional: domain from which the email was scraped"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason",
            "description": "Optional: reason for the opt-out request"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "OptOutRequest",
        "description": "Request body for the privacy opt-out endpoint."
      },
      "OptOutResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "email": {
            "type": "string",
            "title": "Email"
          }
        },
        "type": "object",
        "required": [
          "success",
          "message",
          "email"
        ],
        "title": "OptOutResponse",
        "description": "Response body for the privacy opt-out endpoint."
      },
      "OrgBetaFeatureBulkResponse": {
        "properties": {
          "feature_slug": {
            "type": "string",
            "title": "Feature Slug",
            "description": "Slug of the beta feature that was toggled."
          },
          "affected_users": {
            "type": "integer",
            "title": "Affected Users",
            "description": "Number of org members whose beta feature access was created or removed. Members who already had the feature enabled are not counted for enable-all; members who did not have the feature are not counted for disable-all."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "True if the operation enabled the feature; False if it disabled it."
          }
        },
        "type": "object",
        "required": [
          "feature_slug",
          "affected_users",
          "enabled"
        ],
        "title": "OrgBetaFeatureBulkResponse",
        "description": "Response for org-level bulk beta feature enable/disable operations."
      },
      "OrgRole": {
        "type": "string",
        "enum": [
          "owner",
          "admin",
          "member"
        ],
        "title": "OrgRole",
        "description": "Organization member roles."
      },
      "OrgSessionListResponse": {
        "properties": {
          "personal_sessions": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
            },
            "type": "array",
            "title": "Personal Sessions"
          },
          "team_sessions": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
            },
            "type": "array",
            "title": "Team Sessions"
          },
          "total_personal": {
            "type": "integer",
            "title": "Total Personal"
          },
          "total_team": {
            "type": "integer",
            "title": "Total Team"
          }
        },
        "type": "object",
        "required": [
          "personal_sessions",
          "team_sessions",
          "total_personal",
          "total_team"
        ],
        "title": "OrgSessionListResponse",
        "description": "Response schema for listing organization sessions (personal + shared)."
      },
      "OrganizationCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "OrganizationCreate",
        "description": "Create organization request."
      },
      "OrganizationListResponse": {
        "properties": {
          "organizations": {
            "items": {
              "$ref": "#/components/schemas/OrganizationWithRole"
            },
            "type": "array",
            "title": "Organizations"
          }
        },
        "type": "object",
        "required": [
          "organizations"
        ],
        "title": "OrganizationListResponse",
        "description": "List of organizations response."
      },
      "OrganizationMemberResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "user": {
            "$ref": "#/components/schemas/MemberUser"
          },
          "role": {
            "$ref": "#/components/schemas/OrgRole"
          },
          "joined_at": {
            "type": "string",
            "format": "date-time",
            "title": "Joined At"
          },
          "invited_by": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MemberUser"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "organization_id",
          "user",
          "role",
          "joined_at"
        ],
        "title": "OrganizationMemberResponse",
        "description": "Organization member response."
      },
      "OrganizationStats": {
        "properties": {
          "total_members": {
            "type": "integer",
            "title": "Total Members"
          },
          "total_api_keys": {
            "type": "integer",
            "title": "Total Api Keys"
          },
          "total_webhooks": {
            "type": "integer",
            "title": "Total Webhooks"
          },
          "credits_used_this_period": {
            "type": "integer",
            "title": "Credits Used This Period"
          },
          "credits_allocated": {
            "type": "integer",
            "title": "Credits Allocated"
          },
          "subscription_tier": {
            "type": "string",
            "title": "Subscription Tier",
            "default": "free"
          }
        },
        "type": "object",
        "required": [
          "total_members",
          "total_api_keys",
          "total_webhooks",
          "credits_used_this_period",
          "credits_allocated"
        ],
        "title": "OrganizationStats",
        "description": "Organization statistics."
      },
      "OrganizationUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "settings": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Settings"
          },
          "tenant_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfig"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "title": "OrganizationUpdate",
        "description": "Update organization request."
      },
      "OrganizationWithRole": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "is_personal": {
            "type": "boolean",
            "title": "Is Personal"
          },
          "account_type": {
            "type": "string",
            "title": "Account Type",
            "default": "self_serve"
          },
          "tenant_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Tenant Config"
          },
          "monthly_job_quota": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Monthly Job Quota"
          },
          "role": {
            "$ref": "#/components/schemas/OrgRole"
          },
          "member_count": {
            "type": "integer",
            "title": "Member Count",
            "default": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "is_personal",
          "role",
          "created_at"
        ],
        "title": "OrganizationWithRole",
        "description": "Organization response with user's role."
      },
      "PAAQuestionResponse": {
        "properties": {
          "question": {
            "type": "string",
            "title": "Question",
            "description": "The question text"
          },
          "answer": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Answer",
            "description": "Expanded answer text, if available"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Answer source URL"
          }
        },
        "type": "object",
        "required": [
          "question"
        ],
        "title": "PAAQuestionResponse",
        "description": "A 'People Also Ask' question."
      },
      "PageChanges": {
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "new",
              "changed",
              "same",
              "removed"
            ],
            "title": "Status",
            "description": "Change status relative to the previous crawl"
          },
          "content_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Hash",
            "description": "SHA-256 hash of the current page content"
          },
          "previous_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Hash",
            "description": "SHA-256 hash from the previous crawl (if exists)"
          },
          "previous_crawl_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Crawl Id",
            "description": "Crawl ID that last saw this URL"
          },
          "previous_timestamp": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Timestamp",
            "description": "ISO timestamp when this URL was last crawled"
          },
          "diff": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Diff",
            "description": "Unified text diff (only when include_diff=true and status=changed)"
          },
          "structured_diff": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Structured Diff",
            "description": "Field-level JSON diff with added/removed/changed keys (only when mode=structured, include_diff=true, and status=changed)"
          }
        },
        "type": "object",
        "required": [
          "status"
        ],
        "title": "PageChanges",
        "description": "Change detection result for a single crawled page."
      },
      "PaginationMeta": {
        "properties": {
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Number of results skipped"
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Maximum results per page"
          },
          "total_matching": {
            "type": "integer",
            "title": "Total Matching",
            "description": "Total results matching the filter (before pagination)"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Whether more results exist beyond this page"
          }
        },
        "type": "object",
        "required": [
          "offset",
          "limit",
          "total_matching",
          "has_more"
        ],
        "title": "PaginationMeta",
        "description": "Pagination metadata for paginated responses."
      },
      "PaymentMethodResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "stripe_payment_method_id": {
            "type": "string",
            "title": "Stripe Payment Method Id"
          },
          "type": {
            "type": "string",
            "title": "Type"
          },
          "card_brand": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Brand"
          },
          "card_last4": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Last4"
          },
          "card_exp_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Exp Month"
          },
          "card_exp_year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Exp Year"
          },
          "is_default": {
            "type": "boolean",
            "title": "Is Default"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "stripe_payment_method_id",
          "type",
          "card_brand",
          "card_last4",
          "card_exp_month",
          "card_exp_year",
          "is_default",
          "created_at"
        ],
        "title": "PaymentMethodResponse",
        "description": "Payment method details."
      },
      "PaymentMethodsResponse": {
        "properties": {
          "payment_methods": {
            "items": {
              "$ref": "#/components/schemas/PaymentMethodResponse"
            },
            "type": "array",
            "title": "Payment Methods"
          },
          "default_method_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Method Id"
          },
          "has_billing_account": {
            "type": "boolean",
            "title": "Has Billing Account"
          }
        },
        "type": "object",
        "required": [
          "payment_methods",
          "default_method_id",
          "has_billing_account"
        ],
        "title": "PaymentMethodsResponse",
        "description": "List of payment methods."
      },
      "PayoutHistoryItem": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "gross_cents": {
            "type": "integer",
            "title": "Gross Cents"
          },
          "net_cents": {
            "type": "integer",
            "title": "Net Cents"
          },
          "platform_fee_cents": {
            "type": "integer",
            "title": "Platform Fee Cents"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "gross_cents",
          "net_cents",
          "platform_fee_cents",
          "status",
          "created_at"
        ],
        "title": "PayoutHistoryItem",
        "description": "A single payout event in the history list."
      },
      "PeakHourItem": {
        "properties": {
          "day": {
            "type": "integer",
            "title": "Day"
          },
          "hour": {
            "type": "integer",
            "title": "Hour"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "credits": {
            "type": "integer",
            "title": "Credits"
          }
        },
        "type": "object",
        "required": [
          "day",
          "hour",
          "requests",
          "credits"
        ],
        "title": "PeakHourItem",
        "description": "Peak hour heatmap data point."
      },
      "PeakHoursResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PeakHourItem"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PeakHoursResponse",
        "description": "Peak hours heatmap response."
      },
      "PendingInvitationListResponse": {
        "properties": {
          "invitations": {
            "items": {
              "$ref": "#/components/schemas/InvitationResponse"
            },
            "type": "array",
            "title": "Invitations"
          }
        },
        "type": "object",
        "required": [
          "invitations"
        ],
        "title": "PendingInvitationListResponse",
        "description": "List of pending invitations response."
      },
      "PlanResponse": {
        "properties": {
          "plan_id": {
            "type": "string",
            "title": "Plan Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "monthly_price_cents": {
            "type": "integer",
            "title": "Monthly Price Cents"
          },
          "stripe_price_id": {
            "type": "string",
            "title": "Stripe Price Id"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "plan_id",
          "name",
          "description",
          "monthly_price_cents",
          "stripe_price_id",
          "is_active",
          "created_at"
        ],
        "title": "PlanResponse",
        "description": "Response for a single creator subscription plan."
      },
      "PortalResponse": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "PortalResponse",
        "description": "Customer portal response."
      },
      "PressAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "press",
            "title": "Type",
            "default": "press"
          },
          "key": {
            "type": "string",
            "maxLength": 50,
            "title": "Key",
            "description": "Key to press (e.g., 'Enter', 'Tab', 'Escape', 'ArrowDown')"
          }
        },
        "type": "object",
        "required": [
          "key"
        ],
        "title": "PressAction",
        "description": "Press a keyboard key."
      },
      "ProfilePerformanceStats": {
        "properties": {
          "profile_id": {
            "type": "string",
            "title": "Profile Id",
            "description": "Profile these stats describe."
          },
          "total_queries": {
            "type": "integer",
            "title": "Total Queries",
            "description": "Completed jobs run through this profile.",
            "default": 0
          },
          "total_ads": {
            "type": "integer",
            "title": "Total Ads",
            "description": "Total ads seen across all of this profile's jobs.",
            "default": 0
          },
          "demographic_ads": {
            "type": "integer",
            "title": "Demographic Ads",
            "description": "Ads with is_demographic_ad == true across this profile's jobs.",
            "default": 0
          },
          "demographic_ad_rate": {
            "type": "number",
            "maximum": 1.0,
            "minimum": 0.0,
            "title": "Demographic Ad Rate",
            "description": "demographic_ads / total_ads (0.0 when total_ads == 0).",
            "default": 0.0
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At",
            "description": "Completion time of the most recent job run through this profile."
          },
          "recent_ads": {
            "items": {
              "$ref": "#/components/schemas/ProfileRecentAd"
            },
            "type": "array",
            "title": "Recent Ads",
            "description": "Most recent ads this profile saw (newest first, capped)."
          }
        },
        "type": "object",
        "required": [
          "profile_id"
        ],
        "title": "ProfilePerformanceStats",
        "description": "Aggregated ad-performance stats for a single demographic profile (#28373).\n\nPowers GET /api/v1/b2b/profiles/{profile_id}/stats — the proof-of-value\nlayer on the profile detail page.  Counts aggregate all completed jobs that\nran through this profile (``jobs.payload->>'session_pool_id' == profile_id``)\nfor the calling org.  ``demographic_ad_rate`` is a 0.0-1.0 fraction of ads\ncarrying a demographic targeting reason."
      },
      "ProfileRecentAd": {
        "properties": {
          "advertiser_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Name",
            "description": "Advertiser legal name from Google's Ad Transparency Center."
          },
          "display_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Url",
            "description": "Green display URL shown on the ad."
          },
          "targeting_reasons": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Targeting Reasons",
            "description": "Reason codes explaining why Google served this ad."
          },
          "is_demographic_ad": {
            "type": "boolean",
            "title": "Is Demographic Ad",
            "description": "True when any targeting reason is a demographic code (gender/age/etc.).",
            "default": false
          },
          "query": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Query",
            "description": "Search query the profile ran when this ad was seen."
          },
          "seen_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Seen At",
            "description": "When the job that surfaced this ad completed."
          }
        },
        "type": "object",
        "title": "ProfileRecentAd",
        "description": "One recent ad seen by a demographic profile (#28373).\n\nA thin projection of the ad-identity fields the profile-proof dashboard\nsurfaces in its \"recent ads\" list.  Sourced from completed job ``result``\nJSONB via ``_build_preview_ads`` (the same extraction used by the /results\npreview).  All fields optional so partial/legacy ads serialize cleanly."
      },
      "PromoCodeValidateRequest": {
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 50,
            "minLength": 1,
            "title": "Code"
          }
        },
        "type": "object",
        "required": [
          "code"
        ],
        "title": "PromoCodeValidateRequest",
        "description": "Customer request to validate a promo code."
      },
      "PromoCodeValidateResponse": {
        "properties": {
          "valid": {
            "type": "boolean",
            "title": "Valid"
          },
          "bonus_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bonus Type"
          },
          "bonus_value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bonus Value"
          },
          "max_credits_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits Microcents"
          },
          "max_credits_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Credits Display"
          },
          "min_deposit_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Deposit Cents"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "valid",
          "message"
        ],
        "title": "PromoCodeValidateResponse",
        "description": "Customer view of promo code validation result."
      },
      "ProviderModel": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "context_window": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Context Window"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "title": "ProviderModel",
        "description": "A single model entry from a provider's model catalog."
      },
      "ProviderUsageStats": {
        "properties": {
          "bandwidth_used_bytes": {
            "type": "integer",
            "title": "Bandwidth Used Bytes",
            "default": 0
          },
          "bandwidth_used_gb": {
            "type": "number",
            "title": "Bandwidth Used Gb",
            "default": 0.0
          },
          "bandwidth_limit_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bandwidth Limit Bytes"
          },
          "bandwidth_limit_gb": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bandwidth Limit Gb"
          },
          "bandwidth_percent_used": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bandwidth Percent Used"
          },
          "requests_made": {
            "type": "integer",
            "title": "Requests Made",
            "default": 0
          },
          "requests_limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requests Limit"
          },
          "balance_remaining": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Balance Remaining"
          },
          "currency": {
            "type": "string",
            "title": "Currency",
            "default": "USD"
          },
          "period_start": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period Start"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          },
          "extra": {
            "additionalProperties": true,
            "type": "object",
            "title": "Extra",
            "default": {}
          }
        },
        "type": "object",
        "title": "ProviderUsageStats",
        "description": "Usage statistics from the proxy provider's API."
      },
      "ProxyEndpoint": {
        "properties": {
          "host": {
            "type": "string",
            "title": "Host"
          },
          "port": {
            "type": "integer",
            "title": "Port"
          },
          "protocol": {
            "type": "string",
            "title": "Protocol",
            "default": "http"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Type"
          }
        },
        "type": "object",
        "required": [
          "host",
          "port"
        ],
        "title": "ProxyEndpoint",
        "description": "Cached proxy endpoint from provider API."
      },
      "ProxyIntegrationBatchReorder": {
        "properties": {
          "integrations": {
            "items": {
              "$ref": "#/components/schemas/ProxyIntegrationReorderItem"
            },
            "type": "array",
            "minItems": 1,
            "title": "Integrations",
            "description": "List of integrations with their new priorities"
          }
        },
        "type": "object",
        "required": [
          "integrations"
        ],
        "title": "ProxyIntegrationBatchReorder",
        "description": "Batch reorder proxy integrations by priority."
      },
      "ProxyIntegrationCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Friendly name for this integration (e.g., 'My SmartProxy Account')",
            "examples": [
              "My SmartProxy Account"
            ]
          },
          "provider": {
            "$ref": "#/components/schemas/ProxyProvider",
            "description": "Proxy provider type"
          },
          "credentials": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Credentials",
            "description": "Provider-specific credentials (e.g., api_key, username, password, zone)"
          },
          "is_default": {
            "type": "boolean",
            "title": "Is Default",
            "description": "Set as default proxy provider for all scraping requests",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name",
          "provider",
          "credentials"
        ],
        "title": "ProxyIntegrationCreate",
        "description": "Create a new proxy integration."
      },
      "ProxyIntegrationDetailResponse": {
        "properties": {
          "integration": {
            "$ref": "#/components/schemas/ProxyIntegrationResponse"
          },
          "endpoints": {
            "items": {
              "$ref": "#/components/schemas/ProxyEndpoint"
            },
            "type": "array",
            "title": "Endpoints"
          },
          "available_countries": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Available Countries"
          }
        },
        "type": "object",
        "required": [
          "integration",
          "endpoints",
          "available_countries"
        ],
        "title": "ProxyIntegrationDetailResponse",
        "description": "Detailed proxy integration info with endpoints."
      },
      "ProxyIntegrationListResponse": {
        "properties": {
          "integrations": {
            "items": {
              "$ref": "#/components/schemas/ProxyIntegrationResponse"
            },
            "type": "array",
            "title": "Integrations"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "integrations",
          "total"
        ],
        "title": "ProxyIntegrationListResponse",
        "description": "List of proxy integrations."
      },
      "ProxyIntegrationReorderItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id",
            "description": "Integration ID"
          },
          "priority": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Priority",
            "description": "New priority (lower = higher priority)"
          }
        },
        "type": "object",
        "required": [
          "id",
          "priority"
        ],
        "title": "ProxyIntegrationReorderItem",
        "description": "Single item in batch reorder request."
      },
      "ProxyIntegrationResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "provider": {
            "$ref": "#/components/schemas/ProxyProvider"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "is_default": {
            "type": "boolean",
            "title": "Is Default"
          },
          "priority": {
            "type": "integer",
            "title": "Priority"
          },
          "validation_status": {
            "$ref": "#/components/schemas/ValidationStatus"
          },
          "last_validated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Validated At"
          },
          "validation_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Validation Error"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests"
          },
          "failed_requests": {
            "type": "integer",
            "title": "Failed Requests"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "endpoints_count": {
            "type": "integer",
            "title": "Endpoints Count",
            "default": 0
          },
          "endpoints_refreshed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Endpoints Refreshed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "provider",
          "is_active",
          "is_default",
          "priority",
          "validation_status",
          "total_requests",
          "successful_requests",
          "failed_requests",
          "success_rate",
          "created_at",
          "updated_at"
        ],
        "title": "ProxyIntegrationResponse",
        "description": "Proxy integration details (never exposes credentials)."
      },
      "ProxyIntegrationTestRequest": {
        "properties": {
          "test_url": {
            "type": "string",
            "title": "Test Url",
            "description": "URL to test proxy connectivity against",
            "default": "https://httpbin.org/ip"
          },
          "timeout_seconds": {
            "type": "integer",
            "maximum": 120.0,
            "minimum": 5.0,
            "title": "Timeout Seconds",
            "description": "Request timeout in seconds",
            "default": 30
          }
        },
        "type": "object",
        "title": "ProxyIntegrationTestRequest",
        "description": "Request to test proxy integration connectivity."
      },
      "ProxyIntegrationTestResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "response_time_ms": {
            "type": "integer",
            "title": "Response Time Ms"
          },
          "proxy_ip": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Ip"
          },
          "proxy_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Country"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "success",
          "response_time_ms"
        ],
        "title": "ProxyIntegrationTestResponse",
        "description": "Response from proxy integration test."
      },
      "ProxyIntegrationUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          },
          "is_default": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Default"
          },
          "priority": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Priority"
          }
        },
        "type": "object",
        "title": "ProxyIntegrationUpdate",
        "description": "Update an existing proxy integration."
      },
      "ProxyIntegrationValidateResponse": {
        "properties": {
          "valid": {
            "type": "boolean",
            "title": "Valid"
          },
          "provider": {
            "$ref": "#/components/schemas/ProxyProvider"
          },
          "account_info": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Account Info"
          },
          "available_products": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Available Products"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "valid",
          "provider"
        ],
        "title": "ProxyIntegrationValidateResponse",
        "description": "Response from credential validation."
      },
      "ProxyProvider": {
        "type": "string",
        "enum": [
          "smartproxy",
          "smartproxyorg",
          "brightdata",
          "oxylabs",
          "iproyal",
          "webshare",
          "dataimpulse",
          "netnut"
        ],
        "title": "ProxyProvider",
        "description": "Supported proxy providers."
      },
      "ProxyProviderInfo": {
        "properties": {
          "id": {
            "$ref": "#/components/schemas/ProxyProvider"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "logo_url": {
            "type": "string",
            "title": "Logo Url"
          },
          "website_url": {
            "type": "string",
            "title": "Website Url"
          },
          "docs_url": {
            "type": "string",
            "title": "Docs Url"
          },
          "features": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Features"
          },
          "supported_protocols": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Supported Protocols"
          },
          "requires_username_password": {
            "type": "boolean",
            "title": "Requires Username Password"
          },
          "credential_fields": {
            "items": {
              "$ref": "#/components/schemas/CredentialField"
            },
            "type": "array",
            "title": "Credential Fields",
            "default": []
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "logo_url",
          "website_url",
          "docs_url",
          "features",
          "supported_protocols",
          "requires_username_password"
        ],
        "title": "ProxyProviderInfo",
        "description": "Information about a proxy provider (for UI display)."
      },
      "PublicAnnouncementResponse": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled"
          },
          "text": {
            "type": "string",
            "title": "Text"
          },
          "cta": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicCTA"
              },
              {
                "type": "null"
              }
            ]
          },
          "style": {
            "type": "string",
            "title": "Style"
          },
          "version": {
            "type": "integer",
            "title": "Version"
          }
        },
        "type": "object",
        "required": [
          "enabled",
          "text",
          "cta",
          "style",
          "version"
        ],
        "title": "PublicAnnouncementResponse"
      },
      "PublicAntibotDifficultyResponse": {
        "properties": {
          "days": {
            "type": "integer",
            "title": "Days"
          },
          "generated_at": {
            "type": "string",
            "title": "Generated At"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/PublicAntibotDifficultyRow"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "days",
          "generated_at",
          "data"
        ],
        "title": "PublicAntibotDifficultyResponse"
      },
      "PublicAntibotDifficultyRow": {
        "properties": {
          "vendor": {
            "type": "string",
            "title": "Vendor"
          },
          "difficulty_score": {
            "type": "number",
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Difficulty Score",
            "description": "Normalized difficulty index, 0 (trivial) to 100 (hardest). Derived from success_rate, never the raw bypass %."
          },
          "trend": {
            "$ref": "#/components/schemas/PublicAntibotTrend"
          },
          "sample_size": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Sample Size",
            "description": "Number of scrape encounters this period's aggregate is based on."
          },
          "avg_time_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Time Ms"
          },
          "avg_escalations": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Escalations"
          },
          "most_common_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Most Common Tier"
          }
        },
        "type": "object",
        "required": [
          "vendor",
          "difficulty_score",
          "trend",
          "sample_size"
        ],
        "title": "PublicAntibotDifficultyRow",
        "description": "A single vendor's normalized anti-bot difficulty for the public API.\n\nDeliberately excludes: per-domain data, COGS fields (proxy cost,\nbandwidth), raw bypass success percentage, and any customer/job/billing\nidentifiers. Only a normalized 0-100 difficulty score is published."
      },
      "PublicAntibotTrend": {
        "properties": {
          "direction": {
            "type": "string",
            "enum": [
              "up",
              "down",
              "flat"
            ],
            "title": "Direction"
          },
          "delta": {
            "type": "number",
            "title": "Delta",
            "description": "Signed change in difficulty_score versus the prior period of equal length. Positive means the vendor got harder to bypass."
          }
        },
        "type": "object",
        "required": [
          "direction",
          "delta"
        ],
        "title": "PublicAntibotTrend",
        "description": "Week-over-week (or N-day-over-N-day) change in difficulty score."
      },
      "PublicCTA": {
        "properties": {
          "label": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Label"
          },
          "href": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Href"
          }
        },
        "type": "object",
        "required": [
          "label",
          "href"
        ],
        "title": "PublicCTA",
        "description": "The public, unauthenticated read shape of an announcement CTA.\n\n#31416: prior to this, ``PublicCTA`` had no validator of its own and\ntrusted that ``AnnouncementCTA.validate_href_scheme`` (the *admin\nwrite-path* guard) was the only way an href could ever reach this\nfield. That was true for the one first-party consumer\n(``AnnouncementBar`` via ``resolveBannerState``/``isSafeHref`` in\n``web/src/lib/announcement.ts``, which independently re-validates\nbefore rendering) — but this endpoint is public and unauthenticated,\nso any other client that fetches it directly (a future consumer, a\nthird party, a browser extension) inherited the write-path's\nguarantee with no independent check of its own. Defense-in-depth:\nvalidate here too, using the same shared implementation as the admin\nrouter (``app.core.href_validation``) so this can never drift from\nthe write-path guard.\n\n#31432: the ``Field`` length bounds below also come from\n``app.core.href_validation`` — the same shared constants\n``AnnouncementCTA`` uses — so this stays schema-identical to the\nwrite-path model, not just scheme-identical."
      },
      "PublicKeyResponse": {
        "properties": {
          "available": {
            "type": "boolean",
            "title": "Available",
            "description": "Whether zero-knowledge cookie encryption is configured on this server"
          },
          "key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key",
            "description": "PEM-encoded RSA public key (null when unavailable)"
          },
          "version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version",
            "description": "Key version number, incremented on rotation (null when unavailable)"
          },
          "algorithm": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Algorithm",
            "description": "Key algorithm identifier, e.g. RSA-OAEP-256 (null when unavailable)"
          }
        },
        "type": "object",
        "required": [
          "available"
        ],
        "title": "PublicKeyResponse",
        "description": "Response schema for GET /sessions/public-key."
      },
      "PublicMaintenanceResponse": {
        "properties": {
          "active": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicMaintenanceWindow"
              },
              {
                "type": "null"
              }
            ]
          },
          "upcoming": {
            "items": {
              "$ref": "#/components/schemas/PublicMaintenanceWindow"
            },
            "type": "array",
            "title": "Upcoming"
          }
        },
        "type": "object",
        "required": [
          "active",
          "upcoming"
        ],
        "title": "PublicMaintenanceResponse"
      },
      "PublicMaintenanceWindow": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "title": {
            "type": "string",
            "title": "Title"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "scheduled_start": {
            "type": "string",
            "title": "Scheduled Start"
          },
          "scheduled_end": {
            "type": "string",
            "title": "Scheduled End"
          },
          "actual_start": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actual Start"
          },
          "actual_end": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actual End"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "severity": {
            "type": "string",
            "title": "Severity"
          }
        },
        "type": "object",
        "required": [
          "id",
          "title",
          "description",
          "scheduled_start",
          "scheduled_end",
          "actual_start",
          "actual_end",
          "status",
          "severity"
        ],
        "title": "PublicMaintenanceWindow",
        "description": "Public-safe subset — never exposes created_by/updated_by (internal identity)."
      },
      "PublicStatusResponse": {
        "properties": {
          "overall_status": {
            "type": "string",
            "title": "Overall Status"
          },
          "services": {
            "items": {
              "$ref": "#/components/schemas/ServiceStatus"
            },
            "type": "array",
            "title": "Services"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "title": "Timestamp"
          },
          "uptime_percentage": {
            "type": "number",
            "title": "Uptime Percentage",
            "default": 99.9
          }
        },
        "type": "object",
        "required": [
          "overall_status",
          "services"
        ],
        "title": "PublicStatusResponse",
        "description": "Public status page response.\n\nSimplified status for the public status page.\nDoes not expose internal details or error messages."
      },
      "PublicStorefrontResponse": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "bio": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bio"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "accent_color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Accent Color"
          },
          "templates": {
            "items": {
              "$ref": "#/components/schemas/StorefrontTemplateItem"
            },
            "type": "array",
            "title": "Templates"
          },
          "template_count": {
            "type": "integer",
            "title": "Template Count"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          }
        },
        "type": "object",
        "required": [
          "slug",
          "display_name",
          "bio",
          "logo_url",
          "accent_color",
          "templates",
          "template_count",
          "total",
          "page",
          "limit"
        ],
        "title": "PublicStorefrontResponse",
        "description": "GET /storefronts/{slug} — public view of a creator storefront."
      },
      "PublicTicketCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Submitter display name"
          },
          "email": {
            "type": "string",
            "maxLength": 255,
            "minLength": 3,
            "title": "Email",
            "description": "Submitter email address"
          },
          "subject": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Subject",
            "description": "Ticket subject line (or contact form subject label)"
          },
          "message": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 10,
            "title": "Message",
            "description": "Message body (becomes first reply on the ticket)"
          },
          "category_slug": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Slug",
            "description": "Category slug; omit to let auto-categorisation decide"
          },
          "website": {
            "type": "string",
            "maxLength": 255,
            "title": "Website",
            "description": "Leave empty — anti-bot honeypot field",
            "default": ""
          }
        },
        "type": "object",
        "required": [
          "name",
          "email",
          "subject",
          "message"
        ],
        "title": "PublicTicketCreateRequest",
        "description": "Payload for creating a ticket via the unauthenticated public contact form.\n\nUsed by ``POST /api/v1/support/tickets/public``.\n\nThe ``honeypot`` field is a hidden HTML form field that should always be\nempty when submitted by a real browser. Bots that auto-fill all fields will\npopulate it, allowing the endpoint to reject them silently."
      },
      "PublicTicketResponse": {
        "properties": {
          "ticket_ref": {
            "type": "string",
            "title": "Ticket Ref",
            "description": "Human-readable reference, e.g. ALT-1234"
          },
          "ticket_number": {
            "type": "integer",
            "title": "Ticket Number"
          },
          "subject": {
            "type": "string",
            "title": "Subject"
          },
          "status": {
            "$ref": "#/components/schemas/TicketStatus"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "ticket_ref",
          "ticket_number",
          "subject",
          "status",
          "created_at"
        ],
        "title": "PublicTicketResponse",
        "description": "Minimal ticket response returned from the public endpoint.\n\nIntentionally omits internal fields (user_id, assigned_to, metadata).\nThe ticket_ref is shown to the user so they can reference the ticket\nin follow-up emails."
      },
      "PublishTemplateRequest": {
        "properties": {
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id",
            "description": "ID of the user-owned workflow to publish"
          },
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "Display name for the template"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "What this template does"
          },
          "category": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Category",
            "description": "Category (e.g. Sales, Marketing, Real Estate, Recruiting, E-commerce, Research)"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags",
            "description": "Searchable tags"
          },
          "price_cents": {
            "type": "integer",
            "maximum": 9999999.0,
            "minimum": 0.0,
            "title": "Price Cents",
            "description": "Buyer price in USD cents (0 = free, max $99,999.99). Paid templates require a verified Stripe Connect account.",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "workflow_id",
          "name",
          "category"
        ],
        "title": "PublishTemplateRequest",
        "description": "POST /workflows/templates/publish — submit a workflow as a marketplace template."
      },
      "PublishTemplateResponse": {
        "properties": {
          "template_id": {
            "type": "string",
            "format": "uuid",
            "title": "Template Id"
          },
          "publish_status": {
            "type": "string",
            "title": "Publish Status"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "template_id",
          "publish_status",
          "message"
        ],
        "title": "PublishTemplateResponse",
        "description": "Response after submitting a template for review."
      },
      "QuickDepositRequest": {
        "properties": {
          "amount_cents": {
            "type": "integer",
            "maximum": 200000.0,
            "minimum": 1000.0,
            "title": "Amount Cents",
            "description": "Amount to deposit in cents ($10–$2000)"
          },
          "payment_method_id": {
            "type": "string",
            "format": "uuid",
            "title": "Payment Method Id",
            "description": "Internal payment_methods.id UUID — ownership verified server-side"
          }
        },
        "type": "object",
        "required": [
          "amount_cents",
          "payment_method_id"
        ],
        "title": "QuickDepositRequest",
        "description": "One-click deposit request using a saved payment method.\n\nCharges the user's saved card directly via Stripe PaymentIntent\n(off_session=True, confirm=True) without redirecting to Stripe Checkout."
      },
      "QuickDepositResponse": {
        "properties": {
          "status": {
            "type": "string",
            "title": "Status",
            "description": "PaymentIntent status: 'succeeded', 'requires_action', or 'processing'"
          },
          "amount_cents": {
            "type": "integer",
            "title": "Amount Cents"
          },
          "amount_display": {
            "type": "string",
            "title": "Amount Display"
          },
          "balance_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Balance Display",
            "description": "Updated balance display string (only set when status='succeeded')"
          },
          "client_secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Client Secret",
            "description": "Stripe PaymentIntent client_secret (only set when status='requires_action')"
          }
        },
        "type": "object",
        "required": [
          "status",
          "amount_cents",
          "amount_display"
        ],
        "title": "QuickDepositResponse",
        "description": "Response from a successful or pending quick deposit.\n\nOn synchronous success (non-3DS cards): status='succeeded', balance_display updated.\nOn 3DS required: status='requires_action', client_secret returned for Stripe.js.\nOn async processing (e.g. ACH): status='processing', funds confirmed via webhook."
      },
      "RateShapeConfig": {
        "properties": {
          "jobs_per_hour": {
            "type": "integer",
            "maximum": 500000.0,
            "minimum": 1.0,
            "title": "Jobs Per Hour",
            "description": "Maximum jobs to release per hour from the holding set.",
            "default": 1000
          },
          "burst_limit": {
            "type": "integer",
            "maximum": 10000000.0,
            "minimum": 1.0,
            "title": "Burst Limit",
            "description": "Maximum number of jobs allowed in the holding set at once. Submissions that would exceed this trigger HTTP 429.",
            "default": 50000
          },
          "priority": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 1.0,
            "title": "Priority",
            "description": "Worker queue priority for jobs from this batch. Lower number = higher priority. 1=urgent, 3=high, 5=normal, 7=low, 10=background.",
            "default": 5
          }
        },
        "type": "object",
        "title": "RateShapeConfig",
        "description": "Throughput parameters for releasing jobs from the holding set into the main queue.\n\nThe rate shaping service reads these values when draining\n``b2b:tenant:{org_id}:pending`` into the worker queue."
      },
      "ReactivateSessionResponse": {
        "properties": {
          "reactivated": {
            "type": "boolean",
            "title": "Reactivated"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "type": "object",
        "required": [
          "reactivated"
        ],
        "title": "ReactivateSessionResponse",
        "description": "Response for session reactivation."
      },
      "RecentActivityItem": {
        "properties": {
          "action": {
            "type": "string",
            "title": "Action"
          },
          "resource_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Type"
          },
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "timestamp": {
            "type": "string",
            "title": "Timestamp"
          },
          "details": {
            "type": "string",
            "title": "Details"
          }
        },
        "type": "object",
        "required": [
          "action",
          "resource_type",
          "success",
          "timestamp",
          "details"
        ],
        "title": "RecentActivityItem",
        "description": "Recent billing activity item."
      },
      "RecentActivityResponse": {
        "properties": {
          "activities": {
            "items": {
              "$ref": "#/components/schemas/RecentActivityItem"
            },
            "type": "array",
            "title": "Activities"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "default": 0
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "activities"
        ],
        "title": "RecentActivityResponse",
        "description": "Recent billing activity with pagination."
      },
      "RecentJobResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "mode": {
            "type": "string",
            "title": "Mode"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "proxy_used": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Used"
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "mode",
          "status",
          "credits_used",
          "created_at"
        ],
        "title": "RecentJobResponse",
        "description": "Recent job response."
      },
      "ReferralCodeResponse": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code",
            "description": "Human-readable referral code slug (e.g. 'alice-ref-9x2k')"
          },
          "tier": {
            "type": "integer",
            "maximum": 3.0,
            "minimum": 1.0,
            "title": "Tier",
            "description": "Current tier (1/2/3)"
          },
          "total_referrals": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Total Referrals",
            "description": "Number of successful signups via this code"
          },
          "total_commission_microcents": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Total Commission Microcents",
            "description": "Total commission earned in microcents"
          },
          "commission_rate_bps": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Commission Rate Bps",
            "description": "Current commission rate in basis points (e.g. 1000 = 10%)"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "code",
          "tier",
          "total_referrals",
          "total_commission_microcents",
          "commission_rate_bps",
          "is_active",
          "created_at"
        ],
        "title": "ReferralCodeResponse",
        "description": "Response for GET /referrals/code — the caller's referral code."
      },
      "ReferralEventItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "event_type": {
            "type": "string",
            "title": "Event Type",
            "description": "'signup' or 'purchase_commission'"
          },
          "commission_microcents": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Commission Microcents"
          },
          "source_checkout_session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Checkout Session Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "event_type",
          "commission_microcents",
          "created_at"
        ],
        "title": "ReferralEventItem",
        "description": "A single referral event for the paginated event history."
      },
      "ReferralEventsResponse": {
        "properties": {
          "events": {
            "items": {
              "$ref": "#/components/schemas/ReferralEventItem"
            },
            "type": "array",
            "title": "Events"
          },
          "total": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Total",
            "description": "Total number of events for this referral code"
          },
          "page": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Page"
          },
          "page_size": {
            "type": "integer",
            "minimum": 1.0,
            "title": "Page Size"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More"
          }
        },
        "type": "object",
        "required": [
          "events",
          "total",
          "page",
          "page_size",
          "has_more"
        ],
        "title": "ReferralEventsResponse",
        "description": "Response for GET /referrals/events — paginated event history."
      },
      "ReferralLinkResponse": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          },
          "referral_url": {
            "type": "string",
            "title": "Referral Url"
          },
          "referrer_reward_display": {
            "type": "string",
            "title": "Referrer Reward Display"
          },
          "referee_reward_display": {
            "type": "string",
            "title": "Referee Reward Display"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "code",
          "referral_url",
          "referrer_reward_display",
          "referee_reward_display",
          "is_active",
          "created_at"
        ],
        "title": "ReferralLinkResponse",
        "description": "Response for the user's referral link."
      },
      "ReferralStatsResponse": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          },
          "referral_url": {
            "type": "string",
            "title": "Referral Url"
          },
          "referrals_count": {
            "type": "integer",
            "title": "Referrals Count"
          },
          "successful_referrals": {
            "type": "integer",
            "title": "Successful Referrals"
          },
          "total_credits_earned_display": {
            "type": "string",
            "title": "Total Credits Earned Display"
          },
          "referrer_reward_display": {
            "type": "string",
            "title": "Referrer Reward Display"
          },
          "referee_reward_display": {
            "type": "string",
            "title": "Referee Reward Display"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          }
        },
        "type": "object",
        "required": [
          "code",
          "referral_url",
          "referrals_count",
          "successful_referrals",
          "total_credits_earned_display",
          "referrer_reward_display",
          "referee_reward_display",
          "is_active"
        ],
        "title": "ReferralStatsResponse",
        "description": "Referral performance stats for the dashboard."
      },
      "ReferralValidateRequest": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          }
        },
        "type": "object",
        "required": [
          "code"
        ],
        "title": "ReferralValidateRequest",
        "description": "Request to validate a referral code (used during signup)."
      },
      "ReferralValidateResponse": {
        "properties": {
          "valid": {
            "type": "boolean",
            "title": "Valid"
          },
          "referee_reward_display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Referee Reward Display"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "valid",
          "message"
        ],
        "title": "ReferralValidateResponse",
        "description": "Response for referral code validation."
      },
      "ReplyCreateRequest": {
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 1,
            "title": "Body",
            "description": "Reply body (plain text or markdown)"
          },
          "is_internal_note": {
            "type": "boolean",
            "title": "Is Internal Note",
            "description": "If True, the reply is only visible to admins (admin only)",
            "default": false
          },
          "attachments": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/AttachmentRef"
                },
                "type": "array",
                "maxItems": 10
              },
              {
                "type": "null"
              }
            ],
            "title": "Attachments",
            "description": "Pre-uploaded attachments to link to this reply (max 10)"
          }
        },
        "type": "object",
        "required": [
          "body"
        ],
        "title": "ReplyCreateRequest",
        "description": "Payload for adding a reply to an existing ticket."
      },
      "ReplyListResponse": {
        "properties": {
          "replies": {
            "items": {
              "$ref": "#/components/schemas/ReplyResponse"
            },
            "type": "array",
            "title": "Replies"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size"
          },
          "pages": {
            "type": "integer",
            "title": "Pages"
          }
        },
        "type": "object",
        "required": [
          "replies",
          "total",
          "page",
          "page_size",
          "pages"
        ],
        "title": "ReplyListResponse",
        "description": "Paginated list of replies for a ticket."
      },
      "ReplyResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "ticket_id": {
            "type": "string",
            "format": "uuid",
            "title": "Ticket Id"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "author_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Name",
            "description": "Display name of the reply author (joined at query time)"
          },
          "author_is_admin": {
            "type": "boolean",
            "title": "Author Is Admin",
            "default": false
          },
          "is_admin_reply": {
            "type": "boolean",
            "title": "Is Admin Reply"
          },
          "is_internal_note": {
            "type": "boolean",
            "title": "Is Internal Note"
          },
          "body": {
            "type": "string",
            "title": "Body"
          },
          "body_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Body Html"
          },
          "attachments": {
            "items": {
              "$ref": "#/components/schemas/AttachmentResponse"
            },
            "type": "array",
            "title": "Attachments"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "edited_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Edited At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "ticket_id",
          "is_admin_reply",
          "is_internal_note",
          "body",
          "created_at",
          "updated_at"
        ],
        "title": "ReplyResponse",
        "description": "Full reply representation returned from the API."
      },
      "ReportCreate": {
        "properties": {
          "domain": {
            "type": "string",
            "maxLength": 253,
            "minLength": 1,
            "title": "Domain"
          },
          "url": {
            "type": "string",
            "maxLength": 2048,
            "minLength": 1,
            "title": "Url"
          },
          "title": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "score": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Score"
          },
          "signals": {
            "items": {},
            "type": "array",
            "title": "Signals"
          },
          "anti_bot_stack": {
            "items": {},
            "type": "array",
            "title": "Anti Bot Stack"
          },
          "tech_stack": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tech Stack"
          },
          "pagination": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pagination"
          },
          "api_endpoints": {
            "items": {},
            "type": "array",
            "title": "Api Endpoints"
          },
          "meta": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Meta"
          },
          "cookie_count": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Cookie Count",
            "default": 0
          },
          "has_login_wall": {
            "type": "boolean",
            "title": "Has Login Wall",
            "default": false
          },
          "has_cookie_gate": {
            "type": "boolean",
            "title": "Has Cookie Gate",
            "default": false
          },
          "estimated_credits": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Credits"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "url",
          "score"
        ],
        "title": "ReportCreate",
        "description": "Schema for creating a new scrapability report."
      },
      "RequestLogItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain"
          },
          "tier_used": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier Used"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "default": 0
          },
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status Code"
          },
          "response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Response Time Ms"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mode"
          },
          "job_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Job Id"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source"
          },
          "extraction_method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Method"
          },
          "size_bytes": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Size Bytes"
          }
        },
        "type": "object",
        "required": [
          "id",
          "created_at",
          "success"
        ],
        "title": "RequestLogItem",
        "description": "Single row in the per-key request log."
      },
      "RequestLogResponse": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/RequestLogItem"
            },
            "type": "array",
            "title": "Items"
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "total",
          "page",
          "page_size",
          "total_pages",
          "items"
        ],
        "title": "RequestLogResponse",
        "description": "Paginated request log for a specific API key."
      },
      "RequestTypeItem": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "percentage": {
            "type": "number",
            "title": "Percentage"
          }
        },
        "type": "object",
        "required": [
          "type",
          "requests",
          "percentage"
        ],
        "title": "RequestTypeItem",
        "description": "Request type data item."
      },
      "RequestTypesResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/RequestTypeItem"
            },
            "type": "array",
            "title": "Data"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          }
        },
        "type": "object",
        "required": [
          "data",
          "total_requests"
        ],
        "title": "RequestTypesResponse",
        "description": "Request types response."
      },
      "ResetPasswordRequest": {
        "properties": {
          "token": {
            "type": "string",
            "title": "Token"
          },
          "new_password": {
            "type": "string",
            "title": "New Password"
          }
        },
        "type": "object",
        "required": [
          "token",
          "new_password"
        ],
        "title": "ResetPasswordRequest",
        "description": "Reset password request."
      },
      "ResetPasswordResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "message"
        ],
        "title": "ResetPasswordResponse",
        "description": "Reset password response."
      },
      "ResponseMeta": {
        "properties": {
          "provider": {
            "type": "string",
            "title": "Provider",
            "description": "Data provider identifier",
            "default": "alterlab.io"
          },
          "api_version": {
            "type": "string",
            "title": "Api Version",
            "description": "API version that produced this response",
            "default": "v1"
          }
        },
        "type": "object",
        "title": "ResponseMeta",
        "description": "Attribution metadata included in all scrape responses."
      },
      "ResponseTimeHintResponse": {
        "properties": {
          "sla_targets": {
            "additionalProperties": {
              "type": "number"
            },
            "type": "object",
            "title": "Sla Targets"
          },
          "avg_response_time_hours": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Hours"
          }
        },
        "type": "object",
        "required": [
          "sla_targets"
        ],
        "title": "ResponseTimeHintResponse",
        "description": "Per-priority SLA first-response targets and optional average response time."
      },
      "RetentionPolicyResponse": {
        "properties": {
          "inactive_retention_days": {
            "type": "integer",
            "title": "Inactive Retention Days",
            "description": "Days of inactivity before auto-deletion"
          },
          "expired_retention_days": {
            "type": "integer",
            "title": "Expired Retention Days",
            "description": "Days after cookie expiry before auto-deletion"
          },
          "warning_days_before_deletion": {
            "type": "integer",
            "title": "Warning Days Before Deletion",
            "description": "Days before auto-deletion when warning is sent"
          },
          "data_region": {
            "type": "string",
            "title": "Data Region",
            "description": "Region where session data is stored"
          }
        },
        "type": "object",
        "required": [
          "inactive_retention_days",
          "expired_retention_days",
          "warning_days_before_deletion",
          "data_region"
        ],
        "title": "RetentionPolicyResponse",
        "description": "Current data retention policy settings."
      },
      "RevenuePlanItem": {
        "properties": {
          "plan_id": {
            "type": "string",
            "title": "Plan Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "monthly_price_cents": {
            "type": "integer",
            "title": "Monthly Price Cents"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "subscriber_count": {
            "type": "integer",
            "title": "Subscriber Count"
          },
          "mrr_cents": {
            "type": "integer",
            "title": "Mrr Cents"
          },
          "creator_lifetime_earnings_cents": {
            "type": "integer",
            "title": "Creator Lifetime Earnings Cents"
          }
        },
        "type": "object",
        "required": [
          "plan_id",
          "name",
          "monthly_price_cents",
          "is_active",
          "subscriber_count",
          "mrr_cents",
          "creator_lifetime_earnings_cents"
        ],
        "title": "RevenuePlanItem",
        "description": "Per-plan analytics row.\n\nNote: creator_lifetime_earnings_cents is the creator's total lifetime payout\nacross ALL plans (not per-plan). payout_events has no plan_id FK so per-plan\nbreakdown is not possible with the current schema."
      },
      "RobotsTxtInfo": {
        "properties": {
          "exists": {
            "type": "boolean",
            "title": "Exists",
            "description": "Whether robots.txt was found"
          },
          "disallowed_paths": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Disallowed Paths",
            "description": "Paths disallowed for our user-agent"
          },
          "crawl_delay": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Crawl Delay",
            "description": "Crawl-delay in seconds (if specified)"
          },
          "sitemaps": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Sitemaps",
            "description": "Sitemap URLs listed in robots.txt"
          }
        },
        "type": "object",
        "required": [
          "exists"
        ],
        "title": "RobotsTxtInfo",
        "description": "robots.txt summary for the target domain."
      },
      "RunSummary": {
        "properties": {
          "run_id": {
            "type": "string",
            "title": "Run Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "triggered_by": {
            "type": "string",
            "title": "Triggered By"
          }
        },
        "type": "object",
        "required": [
          "run_id",
          "status",
          "started_at",
          "completed_at",
          "triggered_by"
        ],
        "title": "RunSummary",
        "description": "Condensed workflow run info for buyer purchase view."
      },
      "S3OutputConfig": {
        "properties": {
          "type": {
            "type": "string",
            "const": "s3",
            "title": "Type"
          },
          "bucket": {
            "type": "string",
            "title": "Bucket",
            "description": "S3 bucket name"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix",
            "description": "Key prefix for output files, e.g. 'crawls/2026-03-17/'",
            "default": ""
          },
          "region": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Region",
            "description": "AWS region, e.g. 'us-east-1'"
          },
          "credentials": {
            "$ref": "#/components/schemas/S3OutputCredentials"
          },
          "format": {
            "type": "string",
            "enum": [
              "jsonl",
              "json_per_page",
              "csv"
            ],
            "title": "Format",
            "description": "Output file format",
            "default": "jsonl"
          }
        },
        "type": "object",
        "required": [
          "type",
          "bucket",
          "credentials"
        ],
        "title": "S3OutputConfig",
        "description": "S3 output connector configuration."
      },
      "S3OutputCredentials": {
        "properties": {
          "access_key_id": {
            "type": "string",
            "title": "Access Key Id",
            "description": "AWS access key ID"
          },
          "secret_access_key": {
            "type": "string",
            "title": "Secret Access Key",
            "description": "AWS secret access key"
          }
        },
        "type": "object",
        "required": [
          "access_key_id",
          "secret_access_key"
        ],
        "title": "S3OutputCredentials",
        "description": "AWS S3 credentials for direct export."
      },
      "SatisfactionRequest": {
        "properties": {
          "rating": {
            "type": "integer",
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Rating",
            "description": "Satisfaction rating from 1 (very dissatisfied) to 5 (very satisfied)"
          },
          "comment": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Comment",
            "description": "Optional free-text feedback"
          }
        },
        "type": "object",
        "required": [
          "rating"
        ],
        "title": "SatisfactionRequest",
        "description": "Payload for submitting a CSAT rating on a resolved ticket."
      },
      "SaveTemplateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Display name for the template"
          },
          "schema": {
            "additionalProperties": true,
            "type": "object",
            "title": "Schema",
            "description": "JSON Schema defining the extraction output structure"
          }
        },
        "type": "object",
        "required": [
          "name",
          "schema"
        ],
        "title": "SaveTemplateRequest",
        "description": "Request body for POST /v1/extract/templates."
      },
      "SaveTemplateResponse": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "schema": {
            "additionalProperties": true,
            "type": "object",
            "title": "Schema"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "schema",
          "created_at"
        ],
        "title": "SaveTemplateResponse",
        "description": "Response for POST /v1/extract/templates."
      },
      "ScheduleAnalyticsResponse": {
        "properties": {
          "active_count": {
            "type": "integer",
            "title": "Active Count"
          },
          "total_count": {
            "type": "integer",
            "title": "Total Count"
          },
          "total_runs_30d": {
            "type": "integer",
            "title": "Total Runs 30D"
          },
          "success_rate_30d": {
            "type": "number",
            "title": "Success Rate 30D"
          },
          "total_credits_30d": {
            "type": "integer",
            "title": "Total Credits 30D"
          },
          "schedules": {
            "items": {
              "$ref": "#/components/schemas/ScheduleHealthItem"
            },
            "type": "array",
            "title": "Schedules"
          },
          "forecast": {
            "$ref": "#/components/schemas/CreditForecast"
          }
        },
        "type": "object",
        "required": [
          "active_count",
          "total_count",
          "total_runs_30d",
          "success_rate_30d",
          "total_credits_30d",
          "schedules",
          "forecast"
        ],
        "title": "ScheduleAnalyticsResponse",
        "description": "Aggregate analytics across all user schedules."
      },
      "ScheduleCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "urls": {
            "items": {
              "type": "string",
              "maxLength": 2083,
              "minLength": 1,
              "format": "uri"
            },
            "type": "array",
            "maxItems": 100,
            "minItems": 1,
            "title": "Urls"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "cron": {
            "type": "string",
            "title": "Cron",
            "description": "Cron expression (5 fields), e.g. '0 9 * * *'"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "BYOS session ID to apply to all URLs on each scheduled run. Session is validated at creation time and re-validated on each execution."
          },
          "export": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ScheduleExportConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cloud storage export config — results uploaded on schedule run completion"
          }
        },
        "type": "object",
        "required": [
          "name",
          "urls",
          "cron"
        ],
        "title": "ScheduleCreateRequest",
        "description": "Create a new scrape schedule."
      },
      "ScheduleExportConfig": {
        "properties": {
          "integration_id": {
            "type": "string",
            "format": "uuid",
            "title": "Integration Id",
            "description": "Storage integration ID to export to"
          },
          "prefix": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Prefix",
            "description": "Key prefix override (uses integration default if not set)"
          },
          "format": {
            "type": "string",
            "enum": [
              "jsonl",
              "csv",
              "json"
            ],
            "title": "Format",
            "description": "Export file format",
            "default": "jsonl"
          }
        },
        "type": "object",
        "required": [
          "integration_id"
        ],
        "title": "ScheduleExportConfig",
        "description": "Export configuration for schedule results to cloud storage."
      },
      "ScheduleExportResponse": {
        "properties": {
          "integration_id": {
            "type": "string",
            "title": "Integration Id"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix",
            "default": ""
          },
          "format": {
            "type": "string",
            "title": "Format",
            "default": "jsonl"
          }
        },
        "type": "object",
        "required": [
          "integration_id"
        ],
        "title": "ScheduleExportResponse",
        "description": "Export config as returned in schedule responses."
      },
      "ScheduleHealthItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "last_run_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run Status"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "avg_credits_per_run": {
            "type": "number",
            "title": "Avg Credits Per Run"
          },
          "total_credits_30d": {
            "type": "integer",
            "title": "Total Credits 30D"
          },
          "trend": {
            "type": "string",
            "title": "Trend",
            "default": "stable"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "cron",
          "is_active",
          "run_count",
          "failure_count",
          "success_rate",
          "avg_credits_per_run",
          "total_credits_30d"
        ],
        "title": "ScheduleHealthItem",
        "description": "Per-schedule health summary for analytics."
      },
      "ScheduleListResponse": {
        "properties": {
          "schedules": {
            "items": {
              "$ref": "#/components/schemas/ScheduleResponse"
            },
            "type": "array",
            "title": "Schedules"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "schedules",
          "total"
        ],
        "title": "ScheduleListResponse",
        "description": "List of schedules."
      },
      "ScheduleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "urls": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Urls"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "cron": {
            "type": "string",
            "title": "Cron"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "options": {
            "additionalProperties": true,
            "type": "object",
            "title": "Options",
            "default": {}
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id"
          },
          "export": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ScheduleExportResponse"
              },
              {
                "type": "null"
              }
            ]
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "next_run_at": {
            "type": "string",
            "format": "date-time",
            "title": "Next Run At"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "urls",
          "cron",
          "timezone",
          "is_active",
          "next_run_at",
          "run_count",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "ScheduleResponse",
        "description": "Schedule detail response."
      },
      "ScheduleRunListResponse": {
        "properties": {
          "runs": {
            "items": {
              "$ref": "#/components/schemas/ScheduleRunResponse"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "runs",
          "total"
        ],
        "title": "ScheduleRunListResponse",
        "description": "List of schedule runs."
      },
      "ScheduleRunResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "job_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Job Ids"
          },
          "batch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Batch Id"
          },
          "urls_total": {
            "type": "integer",
            "title": "Urls Total"
          },
          "urls_completed": {
            "type": "integer",
            "title": "Urls Completed"
          },
          "urls_failed": {
            "type": "integer",
            "title": "Urls Failed"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "status",
          "urls_total",
          "urls_completed",
          "urls_failed",
          "credits_used",
          "created_at"
        ],
        "title": "ScheduleRunResponse",
        "description": "Schedule run execution record."
      },
      "ScheduleUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "urls": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "maxLength": 2083,
                  "minLength": 1,
                  "format": "uri"
                },
                "type": "array",
                "maxItems": 100,
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Urls"
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats"
          },
          "cron": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "options": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Options"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "BYOS session ID to apply on each scheduled run. Set to null to remove session binding."
          },
          "export": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ScheduleExportConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cloud storage export config (set to null to remove)"
          }
        },
        "type": "object",
        "title": "ScheduleUpdateRequest",
        "description": "Update an existing schedule."
      },
      "ScrapeFeedbackRequest": {
        "properties": {
          "job_id": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Job Id",
            "description": "Job ID of the scrape request"
          },
          "issue_type": {
            "$ref": "#/components/schemas/FeedbackIssueType",
            "description": "Type of issue being reported"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "User's description of the issue"
          },
          "expected_content": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Expected Content",
            "description": "What the user expected to receive"
          }
        },
        "type": "object",
        "required": [
          "job_id",
          "issue_type"
        ],
        "title": "ScrapeFeedbackRequest",
        "description": "Request body for submitting scrape feedback.\n\nSubmitted by users via the Playground \"Report Issue\" button.",
        "example": {
          "description": "Product price and availability are missing from the response",
          "expected_content": "Should include price, stock status, and shipping info",
          "issue_type": "incomplete_scrape",
          "job_id": "550e8400-e29b-41d4-a716-446655440000"
        }
      },
      "ScrapeFeedbackResponse": {
        "properties": {
          "feedback_id": {
            "type": "string",
            "title": "Feedback Id",
            "description": "Unique ID for this feedback"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Status of the feedback submission",
            "default": "received"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "User-facing message",
            "default": "Thank you for your feedback. It will be analyzed to improve scraping quality."
          },
          "analysis_queued": {
            "type": "boolean",
            "title": "Analysis Queued",
            "description": "Whether immediate analysis was queued",
            "default": true
          },
          "support_ticket_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Support Ticket Id",
            "description": "UUID of the auto-created support ticket, if created"
          },
          "support_ticket_ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Support Ticket Ref",
            "description": "Human-readable support ticket reference (e.g. ALT-1234)"
          }
        },
        "type": "object",
        "required": [
          "feedback_id"
        ],
        "title": "ScrapeFeedbackResponse",
        "description": "Response after submitting scrape feedback."
      },
      "ScrapeJSRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "method": {
            "type": "string",
            "title": "Method",
            "default": "GET"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers"
          },
          "timeout": {
            "type": "integer",
            "maximum": 300.0,
            "minimum": 1.0,
            "title": "Timeout",
            "default": 90
          },
          "follow_redirects": {
            "type": "boolean",
            "title": "Follow Redirects",
            "default": true
          },
          "wait_for": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wait For"
          },
          "screenshot": {
            "type": "boolean",
            "title": "Screenshot",
            "default": false
          },
          "wait_until": {
            "type": "string",
            "title": "Wait Until",
            "default": "networkidle"
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "default": false
          },
          "include_raw_html": {
            "type": "boolean",
            "title": "Include Raw Html",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "ScrapeJSRequest",
        "description": "JavaScript rendering request."
      },
      "ScrapeLightRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "method": {
            "type": "string",
            "title": "Method",
            "default": "GET"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers"
          },
          "timeout": {
            "type": "integer",
            "maximum": 300.0,
            "minimum": 1.0,
            "title": "Timeout",
            "default": 90
          },
          "follow_redirects": {
            "type": "boolean",
            "title": "Follow Redirects",
            "default": true
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "default": false
          },
          "include_raw_html": {
            "type": "boolean",
            "title": "Include Raw Html",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "ScrapeLightRequest",
        "description": "Light scraping request."
      },
      "ScrapeOCRRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "language": {
            "type": "string",
            "title": "Language",
            "default": "eng"
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "ScrapeOCRRequest",
        "description": "OCR scraping request."
      },
      "ScrapePDFRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "format": {
            "type": "string",
            "pattern": "^(text|markdown)$",
            "title": "Format",
            "default": "markdown"
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "ScrapePDFRequest",
        "description": "PDF scraping request."
      },
      "ScrapeResponse": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          },
          "final_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Final Url",
            "description": "The URL after all redirects resolved. Equals `url` when no redirect occurred or when `follow_redirects=false`. Always populated on successful scrapes."
          },
          "redirected": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirected",
            "description": "True if the scraper followed one or more redirects before reaching the final page (`final_url != url`). False when no redirect occurred. Null on error paths."
          },
          "redirect_chain": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirect Chain",
            "description": "Ordered list of redirect hops, each with `url` and `status_code`. Populated for T1–T3 (curl_cffi) tiers when redirects occur. Null when no redirects occurred or when using T4 (browser) tier."
          },
          "status_code": {
            "type": "integer",
            "title": "Status Code"
          },
          "content": {
            "type": "string",
            "title": "Content"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "published_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "headers": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Headers"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "response_time_ms": {
            "type": "integer",
            "title": "Response Time Ms"
          },
          "size_bytes": {
            "type": "integer",
            "title": "Size Bytes"
          },
          "structured_content": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Structured Content"
          },
          "structured_sections": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Structured Sections"
          },
          "raw_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Raw Html"
          },
          "warning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warning"
          },
          "content_quality": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Quality"
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note"
          },
          "_meta": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ResponseMeta"
              },
              {
                "type": "null"
              }
            ],
            "description": "Attribution metadata identifying AlterLab as the data provider."
          }
        },
        "type": "object",
        "required": [
          "url",
          "status_code",
          "content",
          "headers",
          "cached",
          "credits_used",
          "response_time_ms",
          "size_bytes"
        ],
        "title": "ScrapeResponse",
        "description": "Scrape response."
      },
      "ScrapeTemplateDetailResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id",
            "description": "Template UUID"
          },
          "slug": {
            "type": "string",
            "title": "Slug",
            "description": "URL-safe unique identifier"
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Human-readable template name"
          },
          "description": {
            "type": "string",
            "title": "Description",
            "description": "What this template does",
            "default": ""
          },
          "url_pattern": {
            "type": "string",
            "title": "Url Pattern",
            "description": "URL glob pattern this template targets (e.g. amazon.com/dp/*)",
            "default": ""
          },
          "request_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Request Config",
            "description": "Subset of UnifiedScrapeRequest fields (minus url)"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags",
            "description": "Categorisation tags"
          },
          "use_count": {
            "type": "integer",
            "title": "Use Count",
            "description": "Number of times this template has been used",
            "default": 0
          },
          "created_by_team": {
            "type": "boolean",
            "title": "Created By Team",
            "description": "Whether this template is maintained by the AlterLab team",
            "default": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the template was created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At",
            "description": "When the template was last updated"
          }
        },
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "created_at",
          "updated_at"
        ],
        "title": "ScrapeTemplateDetailResponse",
        "description": "Response for GET /v1/templates/{slug} — same shape as list item."
      },
      "ScrapeTemplateItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id",
            "description": "Template UUID"
          },
          "slug": {
            "type": "string",
            "title": "Slug",
            "description": "URL-safe unique identifier"
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Human-readable template name"
          },
          "description": {
            "type": "string",
            "title": "Description",
            "description": "What this template does",
            "default": ""
          },
          "url_pattern": {
            "type": "string",
            "title": "Url Pattern",
            "description": "URL glob pattern this template targets (e.g. amazon.com/dp/*)",
            "default": ""
          },
          "request_config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Request Config",
            "description": "Subset of UnifiedScrapeRequest fields (minus url)"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags",
            "description": "Categorisation tags"
          },
          "use_count": {
            "type": "integer",
            "title": "Use Count",
            "description": "Number of times this template has been used",
            "default": 0
          },
          "created_by_team": {
            "type": "boolean",
            "title": "Created By Team",
            "description": "Whether this template is maintained by the AlterLab team",
            "default": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the template was created"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At",
            "description": "When the template was last updated"
          }
        },
        "type": "object",
        "required": [
          "id",
          "slug",
          "name",
          "created_at",
          "updated_at"
        ],
        "title": "ScrapeTemplateItem",
        "description": "A single scrape template returned in list and detail responses."
      },
      "ScrapeTemplateListResponse": {
        "properties": {
          "templates": {
            "items": {
              "$ref": "#/components/schemas/ScrapeTemplateItem"
            },
            "type": "array",
            "title": "Templates"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of matching templates"
          },
          "page": {
            "type": "integer",
            "title": "Page",
            "description": "Current page number (1-based)"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size",
            "description": "Number of templates per page"
          }
        },
        "type": "object",
        "required": [
          "templates",
          "total",
          "page",
          "page_size"
        ],
        "title": "ScrapeTemplateListResponse",
        "description": "Paginated response for GET /v1/templates."
      },
      "ScreenshotAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "screenshot",
            "title": "Type",
            "default": "screenshot"
          },
          "full_page": {
            "type": "boolean",
            "title": "Full Page",
            "description": "Capture full page or just viewport",
            "default": true
          }
        },
        "type": "object",
        "title": "ScreenshotAction",
        "description": "Capture a screenshot at this point in the action sequence."
      },
      "ScrollAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "scroll",
            "title": "Type",
            "default": "scroll"
          },
          "direction": {
            "type": "string",
            "enum": [
              "down",
              "up"
            ],
            "title": "Direction",
            "description": "Scroll direction",
            "default": "down"
          },
          "amount": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 1.0,
            "title": "Amount",
            "description": "Number of viewport heights to scroll",
            "default": 1
          }
        },
        "type": "object",
        "title": "ScrollAction",
        "description": "Scroll the page in a direction by a number of viewport heights."
      },
      "SearchCostBreakdown": {
        "properties": {
          "base_cost_microcents": {
            "type": "integer",
            "title": "Base Cost Microcents",
            "description": "Cost for the SERP query itself (varies by engine tier)"
          },
          "scrape_cost_microcents": {
            "type": "integer",
            "title": "Scrape Cost Microcents",
            "description": "Total cost for scraping result pages (sum of per-page tier costs). 0 when scrape_results=false.",
            "default": 0
          },
          "total_microcents": {
            "type": "integer",
            "title": "Total Microcents",
            "description": "Total cost: base_cost_microcents + scrape_cost_microcents"
          },
          "engine": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine",
            "description": "Search engine used for this query (e.g. 'duckduckgo', 'google', 'bing')"
          },
          "engine_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Engine Tier",
            "description": "Pricing tier for the engine: 'standard' (HTTP-only, $0.001/query) or 'browser' (T4 stealth rendering, $0.004/query)"
          }
        },
        "type": "object",
        "required": [
          "base_cost_microcents",
          "total_microcents"
        ],
        "title": "SearchCostBreakdown",
        "description": "Per-call cost breakdown for a search request."
      },
      "SearchRequest": {
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Query",
            "description": "Search terms (max 500 characters)"
          },
          "engine": {
            "type": "string",
            "enum": [
              "duckduckgo",
              "google",
              "bing"
            ],
            "title": "Engine",
            "description": "Search engine to use. 'duckduckgo' (default) is fast and cheap ($0.001/query). 'google' and 'bing' use browser-tier rendering ($0.004/query) for richer results including featured snippets, knowledge panels, and People Also Ask.",
            "default": "duckduckgo"
          },
          "domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain",
            "description": "Restrict results to a specific domain (applied as site: prefix)"
          },
          "num_results": {
            "type": "integer",
            "maximum": 30.0,
            "minimum": 1.0,
            "title": "Num Results",
            "description": "Number of results to return (1-30)",
            "default": 10
          },
          "page": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 1.0,
            "title": "Page",
            "description": "Result page number (1-indexed). Page 2 returns results 11-20, etc.",
            "default": 1
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code for geo-targeted results (e.g., US, GB, DE)"
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Language code for results (e.g., en, fr, de)"
          },
          "time_range": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "hour",
                  "day",
                  "week",
                  "month",
                  "year"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Time Range",
            "description": "Filter results by recency"
          },
          "safe_search": {
            "type": "boolean",
            "title": "Safe Search",
            "description": "Enable safe search filtering (default: true). When false, disables DDG Lite's adult content filter (sends p=-1 instead of p=-2).",
            "default": true
          },
          "tenant_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenant Id",
            "description": "B2B tenant identifier for engine routing (e.g. 'marcode'). Internal use."
          },
          "session_pool_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "pattern": "^[a-zA-Z0-9_\\-.]+$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Pool Id",
            "description": "Explicit session pool identifier for B2B demographic routing (#20410). When set, overrides tenant_id as the pool key passed to SerpSessionPool.acquire_session(), enabling per-profile ad result collection from separate demographic session pools under the same tenant. Falls back to tenant_id when absent. Internal use."
          },
          "scrape_results": {
            "type": "boolean",
            "title": "Scrape Results",
            "description": "If true, scrape each result page and include content in response",
            "default": false
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown",
                    "rag",
                    "content"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats when scrape_results=true"
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON schema for structured extraction (when scrape_results=true)"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "query"
        ],
        "title": "SearchRequest",
        "description": "Request body for POST /v1/search."
      },
      "SearchResponse": {
        "properties": {
          "search_id": {
            "type": "string",
            "title": "Search Id",
            "description": "Unique identifier for this search"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query that was executed"
          },
          "results_requested": {
            "type": "integer",
            "title": "Results Requested",
            "description": "Number of results requested by the caller (the num_results parameter)"
          },
          "results_count": {
            "type": "integer",
            "title": "Results Count",
            "description": "Number of results returned in this response"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits consumed for this search"
          },
          "cost_breakdown": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SearchCostBreakdown"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-call cost breakdown showing base search cost and per-page scrape costs. Present on all responses."
          },
          "estimated_total_results": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Total Results",
            "description": "Estimated total results available from the search engine (e.g. ~1,230,000 from Google's result-stats). May be None if the search engine did not report a total."
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            },
            "type": "array",
            "title": "Results",
            "description": "Search results"
          },
          "featured_snippet": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FeaturedSnippetResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "Featured snippet / answer box if present at the top of results"
          },
          "knowledge_panel": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KnowledgePanelResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "Knowledge panel / entity card if present alongside results"
          },
          "people_also_ask": {
            "items": {
              "$ref": "#/components/schemas/PAAQuestionResponse"
            },
            "type": "array",
            "title": "People Also Ask",
            "description": "'People Also Ask' questions related to the query"
          },
          "related_searches": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Related Searches",
            "description": "Related search query suggestions shown at the bottom of results"
          },
          "did_you_mean": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Did You Mean",
            "description": "Search query correction suggestion (e.g. 'Did you mean: ...')"
          },
          "local_results": {
            "items": {
              "$ref": "#/components/schemas/LocalResultResponse"
            },
            "type": "array",
            "title": "Local Results",
            "description": "Local pack / Google Maps business listings (if present)"
          },
          "video_results": {
            "items": {
              "$ref": "#/components/schemas/VideoResultResponse"
            },
            "type": "array",
            "title": "Video Results",
            "description": "Video carousel results (if present)"
          },
          "news_results": {
            "items": {
              "$ref": "#/components/schemas/NewsResultResponse"
            },
            "type": "array",
            "title": "News Results",
            "description": "Top stories / news carousel results (if present)"
          },
          "image_results": {
            "items": {
              "$ref": "#/components/schemas/ImageResultResponse"
            },
            "type": "array",
            "title": "Image Results",
            "description": "Image carousel results (if present)"
          },
          "shopping_results": {
            "items": {
              "$ref": "#/components/schemas/ShoppingResultResponse"
            },
            "type": "array",
            "title": "Shopping Results",
            "description": "Shopping carousel results with product listings (if present)"
          },
          "ad_results": {
            "items": {
              "$ref": "#/components/schemas/AdResultResponse"
            },
            "type": "array",
            "title": "Ad Results",
            "description": "Paid text advertisements (Google #tads and #bottomads slots, if present)"
          },
          "warnings": {
            "items": {
              "$ref": "#/components/schemas/SearchWarning"
            },
            "type": "array",
            "title": "Warnings",
            "description": "Structured warnings indicating response degradation. Empty list when the request was fulfilled as requested."
          }
        },
        "type": "object",
        "required": [
          "search_id",
          "query",
          "results_requested",
          "results_count",
          "credits_used",
          "results"
        ],
        "title": "SearchResponse",
        "description": "Response from POST /v1/search."
      },
      "SearchResult": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url",
            "description": "URL of the search result"
          },
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Title of the search result"
          },
          "snippet": {
            "type": "string",
            "title": "Snippet",
            "description": "Text snippet/description from the search result"
          },
          "position": {
            "type": "integer",
            "title": "Position",
            "description": "Position in search results (1-indexed)"
          },
          "date_published": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date Published",
            "description": "Publication date shown in the search result (e.g. 'Apr 7, 2024')"
          },
          "displayed_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Displayed Url",
            "description": "URL as displayed in the SERP (breadcrumb-style, e.g. 'example.com › page')"
          },
          "sitelinks": {
            "items": {
              "$ref": "#/components/schemas/SitelinkResponse"
            },
            "type": "array",
            "title": "Sitelinks",
            "description": "Sitelinks shown under this result"
          },
          "content": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SearchResultContent"
              },
              {
                "type": "null"
              }
            ],
            "description": "Scraped page content (only when scrape_results=true)"
          },
          "tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier",
            "description": "Scraping tier used for this result page (1-5). Populated when scrape_results=true."
          },
          "cost_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cost Microcents",
            "description": "Cost to scrape this result page in microcents. Populated when scrape_results=true."
          }
        },
        "type": "object",
        "required": [
          "url",
          "title",
          "snippet",
          "position"
        ],
        "title": "SearchResult",
        "description": "A single search result."
      },
      "SearchResultContent": {
        "properties": {
          "text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Text"
          },
          "markdown": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Markdown"
          },
          "html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Html"
          },
          "json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Json"
          },
          "extraction": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction"
          }
        },
        "type": "object",
        "title": "SearchResultContent",
        "description": "Scraped content for a single search result (when scrape_results=true)."
      },
      "SearchScheduleConfig": {
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Query",
            "description": "Search keyword or phrase"
          },
          "num_results": {
            "type": "integer",
            "maximum": 30.0,
            "minimum": 1.0,
            "title": "Num Results",
            "description": "Number of SERP results to fetch",
            "default": 10
          },
          "engine": {
            "type": "string",
            "enum": [
              "duckduckgo",
              "google",
              "bing"
            ],
            "title": "Engine",
            "description": "Search engine to use. DuckDuckGo is fast/cheap; Google and Bing use browser rendering and are billed at a higher rate.",
            "default": "duckduckgo"
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code for geo-targeted results (e.g., US, GB, DE)"
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[a-zA-Z]{2,3}(-[a-zA-Z]{2,4})?$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "BCP 47 language tag for results (e.g., en, fr, zh-Hans, pt-BR)"
          },
          "safe_search": {
            "type": "boolean",
            "title": "Safe Search",
            "description": "Enable safe search filtering",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "SearchScheduleConfig",
        "description": "Frozen search configuration executed on each scheduled run.\n\nMirrors the key fields of SearchRequest but stored as a JSON blob\nso the schedule is self-contained (no user input at execution time)."
      },
      "SearchScheduleConfigResponse": {
        "properties": {
          "query": {
            "type": "string",
            "title": "Query"
          },
          "num_results": {
            "type": "integer",
            "title": "Num Results"
          },
          "engine": {
            "type": "string",
            "title": "Engine",
            "default": "duckduckgo"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language"
          },
          "safe_search": {
            "type": "boolean",
            "title": "Safe Search"
          }
        },
        "type": "object",
        "required": [
          "query",
          "num_results",
          "safe_search"
        ],
        "title": "SearchScheduleConfigResponse",
        "description": "Search config as returned in schedule responses."
      },
      "SearchScheduleCreateRequest": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron",
            "description": "Cron expression (5 fields), e.g. '0 9 * * *'"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "search_config": {
            "$ref": "#/components/schemas/SearchScheduleConfig"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          }
        },
        "type": "object",
        "required": [
          "name",
          "cron",
          "search_config"
        ],
        "title": "SearchScheduleCreateRequest",
        "description": "Create a new SERP search schedule."
      },
      "SearchScheduleListResponse": {
        "properties": {
          "schedules": {
            "items": {
              "$ref": "#/components/schemas/SearchScheduleResponse"
            },
            "type": "array",
            "title": "Schedules"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "schedules",
          "total"
        ],
        "title": "SearchScheduleListResponse",
        "description": "List of search schedules."
      },
      "SearchScheduleResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "cron": {
            "type": "string",
            "title": "Cron"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "search_config": {
            "$ref": "#/components/schemas/SearchScheduleConfigResponse"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "next_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Run At"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "cron",
          "timezone",
          "search_config",
          "is_active",
          "run_count",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "SearchScheduleResponse",
        "description": "Search schedule detail response."
      },
      "SearchScheduleRunListResponse": {
        "properties": {
          "runs": {
            "items": {
              "$ref": "#/components/schemas/SearchScheduleRunResponse"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "runs",
          "total"
        ],
        "title": "SearchScheduleRunListResponse",
        "description": "List of search schedule runs."
      },
      "SearchScheduleRunResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "job_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Job Id"
          },
          "results_count": {
            "type": "integer",
            "title": "Results Count"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "status",
          "results_count",
          "credits_used",
          "created_at"
        ],
        "title": "SearchScheduleRunResponse",
        "description": "Search schedule run execution record."
      },
      "SearchScheduleUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "cron": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "search_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SearchScheduleConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled"
          }
        },
        "type": "object",
        "title": "SearchScheduleUpdateRequest",
        "description": "Update an existing SERP search schedule."
      },
      "SearchStatusResponse": {
        "properties": {
          "search_id": {
            "type": "string",
            "title": "Search Id"
          },
          "query": {
            "type": "string",
            "title": "Query"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "results_requested": {
            "type": "integer",
            "title": "Results Requested",
            "description": "Number of results requested by the caller (the num_results parameter)"
          },
          "results_count": {
            "type": "integer",
            "title": "Results Count",
            "description": "Number of results returned in this response"
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "description": "Number of results with scraped content"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "cost_breakdown": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SearchCostBreakdown"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-call cost breakdown showing base search cost and per-page scrape costs."
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            },
            "type": "array",
            "title": "Results"
          },
          "ad_results": {
            "items": {
              "$ref": "#/components/schemas/AdResultResponse"
            },
            "type": "array",
            "title": "Ad Results",
            "description": "Paid text advertisements (Google #tads and #bottomads slots, if present)"
          }
        },
        "type": "object",
        "required": [
          "search_id",
          "query",
          "status",
          "results_requested",
          "results_count",
          "completed",
          "credits_used",
          "results"
        ],
        "title": "SearchStatusResponse",
        "description": "Response from GET /v1/search/{search_id}."
      },
      "SearchWarning": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code",
            "description": "Machine-readable warning code. E.g. 'scraping_skipped_insufficient_credits'."
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable explanation of the warning"
          }
        },
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "title": "SearchWarning",
        "description": "A structured warning surfaced when a search response is degraded."
      },
      "SearchWithScrapeResponse": {
        "properties": {
          "search_id": {
            "type": "string",
            "title": "Search Id",
            "description": "Unique identifier for this search"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query that was executed"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Status: scraping (results being fetched) or completed",
            "default": "scraping"
          },
          "results_requested": {
            "type": "integer",
            "title": "Results Requested",
            "description": "Number of results requested by the caller (the num_results parameter)"
          },
          "results_count": {
            "type": "integer",
            "title": "Results Count",
            "description": "Number of results returned in this response"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used",
            "description": "Credits consumed (search + estimated scrape credits)"
          },
          "cost_breakdown": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SearchCostBreakdown"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-call cost breakdown showing base search cost and estimated per-page scrape costs."
          },
          "results": {
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            },
            "type": "array",
            "title": "Results",
            "description": "Search results (content populated as scrapes complete)"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Search complete. Results are being scraped. Poll GET /v1/search/{search_id} for progress."
          }
        },
        "type": "object",
        "required": [
          "search_id",
          "query",
          "results_requested",
          "results_count",
          "credits_used",
          "results"
        ],
        "title": "SearchWithScrapeResponse",
        "description": "Response from POST /v1/search when scrape_results=true and results are async."
      },
      "SecretCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Secret name (e.g. SLACK_TOKEN)"
          },
          "value": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 1,
            "title": "Value",
            "description": "Secret value (plaintext)"
          },
          "integration": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Integration"
          }
        },
        "type": "object",
        "required": [
          "name",
          "value"
        ],
        "title": "SecretCreate"
      },
      "SecretListResponse": {
        "properties": {
          "secrets": {
            "items": {
              "$ref": "#/components/schemas/SecretResponse"
            },
            "type": "array",
            "title": "Secrets"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "secrets",
          "total"
        ],
        "title": "SecretListResponse"
      },
      "SecretResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "integration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Integration"
          },
          "masked_value": {
            "type": "string",
            "title": "Masked Value"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "integration",
          "masked_value",
          "created_at",
          "updated_at"
        ],
        "title": "SecretResponse"
      },
      "SecretUpdate": {
        "properties": {
          "value": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 1,
            "title": "Value",
            "description": "New secret value"
          }
        },
        "type": "object",
        "required": [
          "value"
        ],
        "title": "SecretUpdate"
      },
      "SectionFilter": {
        "properties": {
          "min_content_blocks": {
            "type": "integer",
            "minimum": 0.0,
            "title": "Min Content Blocks",
            "description": "Exclude sections with fewer than N content blocks (paragraphs, lists, etc.). Setting to 1 drops heading-only sections.",
            "default": 0
          },
          "exclude_content_types": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclude Content Types",
            "description": "Remove specific content block types from sections before returning. Valid types: paragraph, list, table, image, code, blockquote, dl, details. Example: ['image'] to drop image-only blocks from sections."
          },
          "content_only": {
            "type": "boolean",
            "title": "Content Only",
            "description": "When true, omit the heading field from sections entirely, returning only content blocks. Useful for KB ingestion where headings are noise.",
            "default": false
          }
        },
        "type": "object",
        "title": "SectionFilter",
        "description": "Filtering options for json_v2 section tree output.\n\nApplied as post-processing after section tree is built — does not\naffect extraction, only what's returned. Empty parent sections are\npruned recursively after filtering."
      },
      "SecuritySummary": {
        "properties": {
          "known_ip_count": {
            "type": "integer",
            "title": "Known Ip Count",
            "description": "Number of distinct known IPs"
          },
          "recent_access_count": {
            "type": "integer",
            "title": "Recent Access Count",
            "description": "Access events in the last 7 days"
          },
          "alert_preferences": {
            "$ref": "#/components/schemas/SessionAlertPreferencesResponse"
          },
          "last_access": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AccessLogEntry"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "type": "object",
        "required": [
          "known_ip_count",
          "recent_access_count",
          "alert_preferences"
        ],
        "title": "SecuritySummary",
        "description": "Security summary for the session detail security panel."
      },
      "SendVerificationCodeRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          }
        },
        "type": "object",
        "required": [
          "email"
        ],
        "title": "SendVerificationCodeRequest"
      },
      "SequenceAnalyticsResponse": {
        "properties": {
          "enrollment_id": {
            "type": "string",
            "format": "uuid",
            "title": "Enrollment Id"
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "funnel": {
            "$ref": "#/components/schemas/SequenceFunnelMetrics"
          },
          "replies": {
            "$ref": "#/components/schemas/SequenceReplyMetrics"
          },
          "conversions": {
            "$ref": "#/components/schemas/SequenceConversionMetrics"
          },
          "variants": {
            "items": {
              "$ref": "#/components/schemas/SequenceVariantMetrics"
            },
            "type": "array",
            "title": "Variants",
            "description": "Per-variant metrics from the first ab_split node in the workflow graph. Empty list when no ab_split node is present or no contacts have been dispatched."
          },
          "steps": {
            "items": {
              "$ref": "#/components/schemas/SequenceStepMetrics"
            },
            "type": "array",
            "title": "Steps",
            "description": "Per-node-type success rates across all contact runs in this enrollment."
          }
        },
        "type": "object",
        "required": [
          "enrollment_id",
          "workflow_id",
          "funnel",
          "replies",
          "conversions"
        ],
        "title": "SequenceAnalyticsResponse",
        "description": "GET /workflows/{id}/sequences/{enrollment_id}/analytics response.\n\nAggregates contact-level and run-level metrics for a single sequence enrollment:\nfunnel breakdown, reply rates, conversion rates, optional A/B variant comparison,\nand per-step engagement."
      },
      "SequenceConversionMetrics": {
        "properties": {
          "converted_count": {
            "type": "integer",
            "title": "Converted Count",
            "description": "Contacts with status='converted'."
          },
          "conversion_rate": {
            "type": "number",
            "title": "Conversion Rate",
            "description": "converted_count / dispatched. 0.0 when dispatched=0."
          },
          "bounced_count": {
            "type": "integer",
            "title": "Bounced Count",
            "description": "Contacts with status='bounced'."
          },
          "unsubscribed_count": {
            "type": "integer",
            "title": "Unsubscribed Count",
            "description": "Contacts with status='unsubscribed'."
          }
        },
        "type": "object",
        "required": [
          "converted_count",
          "conversion_rate",
          "bounced_count",
          "unsubscribed_count"
        ],
        "title": "SequenceConversionMetrics",
        "description": "Conversion metrics for a sequence enrollment."
      },
      "SequenceEnrollRequest": {
        "properties": {
          "contact_list_id": {
            "type": "string",
            "format": "uuid",
            "title": "Contact List Id",
            "description": "Contact list to enroll into this sequence"
          },
          "rate_limit_per_hour": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Limit Per Hour",
            "description": "Max contacts dispatched per rolling 1-hour window. NULL = no limit."
          },
          "auto_stop_on_reply": {
            "type": "boolean",
            "title": "Auto Stop On Reply",
            "description": "Skip contacts whose status is 'replied' at dispatch time.",
            "default": true
          },
          "idempotency_key": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "title": "Idempotency Key",
            "description": "Optional client-supplied key. If provided and an enrollment with the same key already exists for this user, the existing enrollment is returned without creating a new one. Prevents duplicate enrollments and double-debits on network retries."
          }
        },
        "type": "object",
        "required": [
          "contact_list_id"
        ],
        "title": "SequenceEnrollRequest",
        "description": "POST /workflows/{id}/sequences body."
      },
      "SequenceEnrollmentItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "contact_list_id": {
            "type": "string",
            "format": "uuid",
            "title": "Contact List Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "rate_limit_per_hour": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Limit Per Hour"
          },
          "total_contacts": {
            "type": "integer",
            "title": "Total Contacts"
          },
          "dispatched_count": {
            "type": "integer",
            "title": "Dispatched Count"
          },
          "completed_count": {
            "type": "integer",
            "title": "Completed Count"
          },
          "failed_count": {
            "type": "integer",
            "title": "Failed Count"
          },
          "skipped_count": {
            "type": "integer",
            "title": "Skipped Count"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "paused_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paused At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "workflow_id",
          "contact_list_id",
          "status",
          "rate_limit_per_hour",
          "total_contacts",
          "dispatched_count",
          "completed_count",
          "failed_count",
          "skipped_count",
          "started_at",
          "completed_at",
          "paused_at",
          "created_at"
        ],
        "title": "SequenceEnrollmentItem",
        "description": "Enrollment summary for list and detail responses."
      },
      "SequenceEnrollmentListResponse": {
        "properties": {
          "enrollments": {
            "items": {
              "$ref": "#/components/schemas/SequenceEnrollmentItem"
            },
            "type": "array",
            "title": "Enrollments"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "limit": {
            "type": "integer",
            "title": "Limit"
          },
          "total_pages": {
            "type": "integer",
            "title": "Total Pages"
          }
        },
        "type": "object",
        "required": [
          "enrollments",
          "total",
          "page",
          "limit",
          "total_pages"
        ],
        "title": "SequenceEnrollmentListResponse",
        "description": "GET /workflows/{id}/sequences response."
      },
      "SequenceEnrollmentUpdate": {
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "paused",
              "active"
            ],
            "title": "Status",
            "description": "'paused' = pause entire enrollment; 'active' = resume a paused enrollment"
          }
        },
        "type": "object",
        "required": [
          "status"
        ],
        "title": "SequenceEnrollmentUpdate",
        "description": "PATCH /workflows/{id}/sequences/{enrollment_id} body."
      },
      "SequenceFunnelMetrics": {
        "properties": {
          "total_contacts": {
            "type": "integer",
            "title": "Total Contacts",
            "description": "Total contacts enrolled."
          },
          "dispatched": {
            "type": "integer",
            "title": "Dispatched",
            "description": "Contacts with at least one run dispatched."
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "description": "Contacts whose run completed successfully."
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "description": "Contacts whose run failed."
          },
          "skipped": {
            "type": "integer",
            "title": "Skipped",
            "description": "Contacts skipped (e.g. auto_stop_on_reply)."
          },
          "pending": {
            "type": "integer",
            "title": "Pending",
            "description": "Contacts not yet dispatched."
          },
          "completion_rate": {
            "type": "number",
            "title": "Completion Rate",
            "description": "completed / dispatched. 0.0 when dispatched=0."
          },
          "failure_rate": {
            "type": "number",
            "title": "Failure Rate",
            "description": "failed / dispatched. 0.0 when dispatched=0."
          },
          "skip_rate": {
            "type": "number",
            "title": "Skip Rate",
            "description": "skipped / total_contacts. 0.0 when total=0."
          }
        },
        "type": "object",
        "required": [
          "total_contacts",
          "dispatched",
          "completed",
          "failed",
          "skipped",
          "pending",
          "completion_rate",
          "failure_rate",
          "skip_rate"
        ],
        "title": "SequenceFunnelMetrics",
        "description": "Funnel breakdown for a sequence enrollment."
      },
      "SequenceReplyMetrics": {
        "properties": {
          "reply_count": {
            "type": "integer",
            "title": "Reply Count",
            "description": "Total positive replies received."
          },
          "reply_rate": {
            "type": "number",
            "title": "Reply Rate",
            "description": "reply_count / dispatched. 0.0 when dispatched=0."
          },
          "positive_count": {
            "type": "integer",
            "title": "Positive Count",
            "description": "Replies classified as 'positive'."
          },
          "ooo_count": {
            "type": "integer",
            "title": "Ooo Count",
            "description": "Replies classified as out-of-office."
          },
          "unsubscribe_count": {
            "type": "integer",
            "title": "Unsubscribe Count",
            "description": "Replies classified as unsubscribe requests."
          }
        },
        "type": "object",
        "required": [
          "reply_count",
          "reply_rate",
          "positive_count",
          "ooo_count",
          "unsubscribe_count"
        ],
        "title": "SequenceReplyMetrics",
        "description": "Reply-event breakdown for a sequence enrollment."
      },
      "SequenceStepMetrics": {
        "properties": {
          "node_type": {
            "type": "string",
            "title": "Node Type",
            "description": "Workflow node type (e.g. 'email', 'http_request')."
          },
          "attempts": {
            "type": "integer",
            "title": "Attempts",
            "description": "Number of runs where this node type was executed."
          },
          "successes": {
            "type": "integer",
            "title": "Successes",
            "description": "Runs where this node type completed successfully."
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "description": "successes / attempts. 0.0 when attempts=0."
          }
        },
        "type": "object",
        "required": [
          "node_type",
          "attempts",
          "successes",
          "success_rate"
        ],
        "title": "SequenceStepMetrics",
        "description": "Per-step (node-type) engagement metrics across all contact runs."
      },
      "SequenceVariantMetrics": {
        "properties": {
          "variant_key": {
            "type": "string",
            "title": "Variant Key",
            "description": "The variant label assigned by the ab_split node."
          },
          "weight_pct": {
            "type": "number",
            "title": "Weight Pct",
            "description": "Configured weight percentage for this variant."
          },
          "contact_count": {
            "type": "integer",
            "title": "Contact Count",
            "description": "Number of contacts assigned this variant."
          },
          "reply_count": {
            "type": "integer",
            "title": "Reply Count",
            "description": "Replies from contacts assigned this variant."
          },
          "reply_rate": {
            "type": "number",
            "title": "Reply Rate",
            "description": "reply_count / contact_count. 0.0 when count=0."
          },
          "converted_count": {
            "type": "integer",
            "title": "Converted Count",
            "description": "Conversions from contacts assigned this variant."
          },
          "conversion_rate": {
            "type": "number",
            "title": "Conversion Rate",
            "description": "converted_count / contact_count. 0.0 when count=0."
          }
        },
        "type": "object",
        "required": [
          "variant_key",
          "weight_pct",
          "contact_count",
          "reply_count",
          "reply_rate",
          "converted_count",
          "conversion_rate"
        ],
        "title": "SequenceVariantMetrics",
        "description": "Per-variant metrics from an ab_split node in the workflow."
      },
      "SerpAdExtension": {
        "properties": {
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Extension type: 'sitelink', 'callout', 'phone', 'location', 'structured_snippet', 'price', 'promotion', 'app'"
          },
          "text": {
            "type": "string",
            "title": "Text",
            "description": "Extension text content"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url",
            "description": "Extension URL (for sitelinks and other clickable extensions)"
          }
        },
        "type": "object",
        "required": [
          "type",
          "text"
        ],
        "title": "SerpAdExtension",
        "description": "An ad extension (sitelink, callout, phone, etc.)."
      },
      "SerpAdResult": {
        "properties": {
          "position": {
            "type": "integer",
            "title": "Position",
            "description": "Ad position within its placement group (1-indexed)"
          },
          "placement": {
            "type": "string",
            "enum": [
              "top",
              "bottom",
              "sidebar",
              "shopping"
            ],
            "title": "Placement",
            "description": "Where the ad appears on the SERP page"
          },
          "ad_type": {
            "type": "string",
            "enum": [
              "text",
              "shopping",
              "local",
              "video",
              "app"
            ],
            "title": "Ad Type",
            "description": "Ad format type",
            "default": "text"
          },
          "headline": {
            "type": "string",
            "title": "Headline",
            "description": "Primary ad headline text"
          },
          "headline_2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headline 2",
            "description": "Secondary headline (if present)"
          },
          "headline_3": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headline 3",
            "description": "Tertiary headline (if present)"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Ad description / body text"
          },
          "description_2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description 2",
            "description": "Second description line (if present)"
          },
          "display_url": {
            "type": "string",
            "title": "Display Url",
            "description": "URL displayed in the ad (breadcrumb-style, e.g. 'example.com/shoes')"
          },
          "landing_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Landing Url",
            "description": "Final landing URL after redirect chain resolution. May differ from display_url. Null if redirect resolution is disabled or pending."
          },
          "tracking_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tracking Url",
            "description": "Raw click-through URL from the ad (Google's tracking redirect). Resolving this yields the landing_url."
          },
          "advertiser_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Advertiser Name",
            "description": "Verified advertiser name shown by Google (if available)"
          },
          "extensions": {
            "items": {
              "$ref": "#/components/schemas/SerpAdExtension"
            },
            "type": "array",
            "title": "Extensions",
            "description": "Ad extensions (sitelinks, callouts, phone numbers, etc.)"
          },
          "is_brand_ad": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Brand Ad",
            "description": "Whether this ad is placed by the brand being searched for. True when the ad's display domain matches the brand_domain provided in the request. False when a different domain is advertising. Null when brand_domain was not provided in the request or classification could not be determined."
          },
          "is_sponsored": {
            "type": "boolean",
            "title": "Is Sponsored",
            "description": "Whether this is a paid ad (always true for ad results, included for schema clarity)",
            "default": true
          },
          "position_value": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "premium",
                  "standard",
                  "bottom",
                  "shopping"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Position Value",
            "description": "Estimated value tier of this ad position. 'premium' = positions 1-2 in top ads (highest CTR, most expensive). 'standard' = positions 3+ in top ads. 'bottom' = bottom-of-page ads (lowest CTR). 'shopping' = shopping carousel ads."
          },
          "above_fold": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Above Fold",
            "description": "Whether this ad is estimated to appear above the fold (visible without scrolling). Top ads at positions 1-3 are typically above fold on desktop. Bottom and sidebar ads are always below fold."
          },
          "price": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Price",
            "description": "Product price (e.g. '$29.99') — shopping ads only"
          },
          "merchant": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Merchant",
            "description": "Merchant name — shopping ads only"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image Url",
            "description": "Product image URL — shopping ads only"
          },
          "rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating",
            "description": "Star rating (1-5) — shopping ads only"
          },
          "review_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Count",
            "description": "Number of reviews — shopping ads only"
          }
        },
        "type": "object",
        "required": [
          "position",
          "placement",
          "headline",
          "display_url"
        ],
        "title": "SerpAdResult",
        "description": "A single ad result from a Google SERP page.\n\nCaptures the full ad creative including position, text, URLs, and extensions.\nDesigned for ad fraud detection workflows where every field matters."
      },
      "SerpBatchItem": {
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Query",
            "description": "Search query (max 500 characters)"
          },
          "device": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "desktop",
                  "mobile"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Device",
            "description": "Override batch device type for this query"
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Override batch country for this query"
          },
          "city": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "City",
            "description": "Override batch city for this query"
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Override batch language for this query"
          },
          "include_ads": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Include Ads",
            "description": "Override batch include_ads for this query"
          },
          "brand_domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand Domain",
            "description": "Override batch brand_domain for this query"
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "SerpBatchItem",
        "description": "A single query within a batch SERP request.\n\nEach item can override the batch-level defaults for device, country,\nlanguage, and ad extraction settings."
      },
      "SerpBatchItemStatus": {
        "properties": {
          "index": {
            "type": "integer",
            "title": "Index",
            "description": "0-indexed position of this query in the batch"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "completed",
              "failed"
            ],
            "title": "Status",
            "description": "Status of this query"
          },
          "result": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "Full SERP response (when completed)"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message (when failed)"
          }
        },
        "type": "object",
        "required": [
          "index",
          "query",
          "status"
        ],
        "title": "SerpBatchItemStatus",
        "description": "Status of a single query within a batch."
      },
      "SerpBatchRequest": {
        "properties": {
          "queries": {
            "items": {
              "$ref": "#/components/schemas/SerpBatchItem"
            },
            "type": "array",
            "maxItems": 50,
            "minItems": 1,
            "title": "Queries",
            "description": "SERP queries to execute (1-50 items)"
          },
          "search_engine": {
            "type": "string",
            "enum": [
              "google",
              "bing"
            ],
            "title": "Search Engine",
            "description": "Default search engine for all queries",
            "default": "google"
          },
          "device": {
            "type": "string",
            "enum": [
              "desktop",
              "mobile"
            ],
            "title": "Device",
            "description": "Default device type for all queries",
            "default": "desktop"
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Default country for all queries"
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Default language for all queries"
          },
          "include_ads": {
            "type": "boolean",
            "title": "Include Ads",
            "description": "Default ad extraction setting for all queries",
            "default": true
          },
          "brand_domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand Domain",
            "description": "Default brand domain for ad classification across all queries. Can be overridden per query."
          },
          "resolve_redirects": {
            "type": "boolean",
            "title": "Resolve Redirects",
            "description": "Follow redirect chains for ad landing URLs",
            "default": false
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "Reuse a long-lived session for all queries in this batch"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL for result delivery. When set, results are POSTed to this URL as each query completes and again when the full batch is done."
          },
          "webhook_secret": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256,
                "minLength": 8
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Secret",
            "description": "Secret for HMAC-SHA256 webhook signature verification. When provided, all webhook POSTs include an X-AlterLab-Signature header."
          },
          "webhook_per_query": {
            "type": "boolean",
            "title": "Webhook Per Query",
            "description": "When true, fire a webhook for each individual query result (event: serp.completed) in addition to the final batch completion webhook. When false, only fire the batch completion webhook.",
            "default": false
          },
          "max_concurrent": {
            "type": "integer",
            "maximum": 20.0,
            "minimum": 1.0,
            "title": "Max Concurrent",
            "description": "Maximum number of queries to process concurrently within this batch. Lower values reduce proxy burn rate; higher values complete faster. Default: 5.",
            "default": 5
          }
        },
        "type": "object",
        "required": [
          "queries"
        ],
        "title": "SerpBatchRequest",
        "description": "Request body for POST /v1/serp/batch.\n\nSubmit up to 50 SERP queries for asynchronous parallel processing.\nEach query can override batch-level defaults. Results are delivered\nvia polling (GET /v1/serp/batch/{batch_id}) or webhook."
      },
      "SerpBatchResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id",
            "description": "Unique batch identifier for polling"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Batch status",
            "default": "accepted"
          },
          "total_queries": {
            "type": "integer",
            "title": "Total Queries",
            "description": "Number of queries in the batch"
          },
          "estimated_cost_microcents": {
            "type": "integer",
            "title": "Estimated Cost Microcents",
            "description": "Estimated total cost in microcents (actual may vary)"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable status message",
            "default": "Batch accepted. Poll GET /v1/serp/batch/{batch_id} for progress."
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "total_queries",
          "estimated_cost_microcents"
        ],
        "title": "SerpBatchResponse",
        "description": "Response from POST /v1/serp/batch — acknowledgement with batch_id for polling."
      },
      "SerpBatchStatusResponse": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id",
            "description": "Batch identifier"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "partial",
              "failed"
            ],
            "title": "Status",
            "description": "Overall batch status"
          },
          "total_queries": {
            "type": "integer",
            "title": "Total Queries",
            "description": "Total queries in batch"
          },
          "completed": {
            "type": "integer",
            "title": "Completed",
            "description": "Number of completed queries"
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "description": "Number of failed queries"
          },
          "total_cost_microcents": {
            "type": "integer",
            "title": "Total Cost Microcents",
            "description": "Actual total cost so far"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/SerpBatchItemStatus"
            },
            "type": "array",
            "title": "Items",
            "description": "Per-query status and results"
          },
          "webhook_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Status",
            "description": "Webhook delivery status: pending, delivered, retrying, failed, or null if no webhook configured"
          },
          "webhook_attempts": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Attempts",
            "description": "Number of webhook delivery attempts made (null if no webhook configured)"
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "status",
          "total_queries",
          "completed",
          "failed",
          "total_cost_microcents",
          "items"
        ],
        "title": "SerpBatchStatusResponse",
        "description": "Response from GET /v1/serp/batch/{batch_id} — batch progress and results."
      },
      "SerpChangeSummary": {
        "properties": {
          "from_timestamp": {
            "type": "string",
            "format": "date-time",
            "title": "From Timestamp",
            "description": "Earlier snapshot timestamp"
          },
          "to_timestamp": {
            "type": "string",
            "format": "date-time",
            "title": "To Timestamp",
            "description": "Later snapshot timestamp"
          },
          "new_advertisers": {
            "items": {
              "$ref": "#/components/schemas/AdvertiserChange"
            },
            "type": "array",
            "title": "New Advertisers",
            "description": "Advertisers that appeared in the later snapshot but not the earlier"
          },
          "dropped_advertisers": {
            "items": {
              "$ref": "#/components/schemas/AdvertiserChange"
            },
            "type": "array",
            "title": "Dropped Advertisers",
            "description": "Advertisers present in the earlier snapshot but absent in the later"
          },
          "position_changes": {
            "items": {
              "$ref": "#/components/schemas/AdvertiserChange"
            },
            "type": "array",
            "title": "Position Changes",
            "description": "Advertisers whose position changed between snapshots"
          },
          "ads_count_delta": {
            "type": "integer",
            "title": "Ads Count Delta",
            "description": "Change in total ads count (positive = more ads)",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "from_timestamp",
          "to_timestamp"
        ],
        "title": "SerpChangeSummary",
        "description": "Change detection between two consecutive snapshots."
      },
      "SerpCompetitiveMetrics": {
        "properties": {
          "total_advertisers": {
            "type": "integer",
            "title": "Total Advertisers",
            "description": "Number of unique advertisers (deduplicated by domain) across all ad placements on this SERP.",
            "default": 0
          },
          "brand_share_of_voice": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand Share Of Voice",
            "description": "Brand's share of ad inventory on this SERP, computed as (brand ad count / total ad count). Range 0.0-1.0. Requires brand_domain in the request — null otherwise."
          },
          "top_position_holder": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Top Position Holder",
            "description": "Domain holding position 1 in top ads. Null when no top ads are present."
          },
          "ad_density": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "medium",
              "high"
            ],
            "title": "Ad Density",
            "description": "Ad density classification based on total ad count: 'none' (0 ads), 'low' (1-3 ads), 'medium' (4-7 ads), 'high' (8+ ads).",
            "default": "none"
          },
          "estimated_competition_level": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "medium",
              "high"
            ],
            "title": "Estimated Competition Level",
            "description": "Estimated competition level based on ad count and shopping ad presence. Higher when both text and shopping ads compete for the same query.",
            "default": "none"
          }
        },
        "type": "object",
        "title": "SerpCompetitiveMetrics",
        "description": "Per-query competitive intelligence metrics derived from ad data.\n\nThese fields turn raw ad extraction into actionable business insights.\nAll metrics are computed from data already extracted — no additional\nscraping is required. Fields are null when insufficient data is available."
      },
      "SerpCostBreakdown": {
        "properties": {
          "base_cost_microcents": {
            "type": "integer",
            "title": "Base Cost Microcents",
            "description": "Base SERP scrape cost in microcents (includes browser rendering)"
          },
          "ad_extraction_cost_microcents": {
            "type": "integer",
            "title": "Ad Extraction Cost Microcents",
            "description": "Additional cost for ad extraction (redirect resolution, advertiser lookup)",
            "default": 0
          },
          "captcha_solve_cost_microcents": {
            "type": "integer",
            "title": "Captcha Solve Cost Microcents",
            "description": "Cost of CAPTCHA solving in microcents. Non-zero when a reCAPTCHA challenge was encountered and solved via CapSolver.",
            "default": 0
          },
          "total_cost_microcents": {
            "type": "integer",
            "title": "Total Cost Microcents",
            "description": "Total cost in microcents"
          },
          "tier_used": {
            "type": "string",
            "title": "Tier Used",
            "description": "Scraping tier used (typically '4' for browser-rendered SERP)"
          }
        },
        "type": "object",
        "required": [
          "base_cost_microcents",
          "total_cost_microcents",
          "tier_used"
        ],
        "title": "SerpCostBreakdown",
        "description": "Cost breakdown for a SERP request."
      },
      "SerpFeaturedSnippet": {
        "properties": {
          "content": {
            "type": "string",
            "title": "Content",
            "description": "Snippet text content"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Source page URL"
          },
          "source_title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Title",
            "description": "Source page title"
          },
          "snippet_type": {
            "type": "string",
            "title": "Snippet Type",
            "description": "Type: text, list, or table",
            "default": "text"
          }
        },
        "type": "object",
        "required": [
          "content"
        ],
        "title": "SerpFeaturedSnippet",
        "description": "Featured snippet / answer box at the top of search results."
      },
      "SerpHistoryResponse": {
        "properties": {
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query"
          },
          "search_engine": {
            "type": "string",
            "title": "Search Engine",
            "description": "Search engine filter applied"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Country filter applied"
          },
          "total_snapshots": {
            "type": "integer",
            "title": "Total Snapshots",
            "description": "Total number of snapshots matching the query"
          },
          "snapshots": {
            "items": {
              "$ref": "#/components/schemas/SerpSnapshotSummary"
            },
            "type": "array",
            "title": "Snapshots",
            "description": "Time-series snapshots (most recent first)"
          },
          "changes": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpChangeSummary"
              },
              {
                "type": "null"
              }
            ],
            "description": "Change detection between the first and last snapshot in the result set. Only populated when include_changes=true and at least 2 snapshots exist."
          }
        },
        "type": "object",
        "required": [
          "query",
          "search_engine",
          "total_snapshots"
        ],
        "title": "SerpHistoryResponse",
        "description": "Response from GET /v1/serp/history."
      },
      "SerpImageResult": {
        "properties": {
          "image_url": {
            "type": "string",
            "title": "Image Url",
            "description": "Image URL or thumbnail URL"
          },
          "alt_text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Alt Text",
            "description": "Alt text"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Source page URL"
          }
        },
        "type": "object",
        "required": [
          "image_url"
        ],
        "title": "SerpImageResult",
        "description": "An image result from the image carousel."
      },
      "SerpKnowledgePanel": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Entity name"
          },
          "entity_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Entity Type",
            "description": "Entity type (e.g. 'Company', 'Person')"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Entity description"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Source attribution (e.g. 'Wikipedia')"
          },
          "facts": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Facts",
            "description": "Key-value fact pairs"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image Url",
            "description": "Entity image URL"
          }
        },
        "type": "object",
        "required": [
          "title"
        ],
        "title": "SerpKnowledgePanel",
        "description": "Knowledge panel / entity card shown alongside search results."
      },
      "SerpLocalResult": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Business name"
          },
          "address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address",
            "description": "Business address"
          },
          "rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating",
            "description": "Star rating (1-5)"
          },
          "review_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Count",
            "description": "Number of reviews"
          },
          "phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Phone",
            "description": "Phone number"
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category",
            "description": "Business category"
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "SerpLocalResult",
        "description": "A local pack result (business listing)."
      },
      "SerpNewsResult": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "News headline"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Article URL"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Publisher name"
          },
          "date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date",
            "description": "Publication date"
          },
          "thumbnail_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thumbnail Url",
            "description": "Thumbnail URL"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "SerpNewsResult",
        "description": "A news result from the top stories / news carousel."
      },
      "SerpOrganicResult": {
        "properties": {
          "position": {
            "type": "integer",
            "title": "Position",
            "description": "1-indexed position on the page"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Result URL"
          },
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Result title"
          },
          "snippet": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Snippet",
            "description": "Result snippet/description"
          },
          "displayed_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Displayed Url",
            "description": "URL as displayed in the SERP (breadcrumb-style)"
          },
          "date_published": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date Published",
            "description": "Date shown next to the result, if any"
          },
          "sitelinks": {
            "items": {
              "$ref": "#/components/schemas/SerpSitelink"
            },
            "type": "array",
            "title": "Sitelinks",
            "description": "Sitelinks under this result"
          }
        },
        "type": "object",
        "required": [
          "position",
          "url",
          "title"
        ],
        "title": "SerpOrganicResult",
        "description": "A single organic (non-paid) search result."
      },
      "SerpPAAQuestion": {
        "properties": {
          "question": {
            "type": "string",
            "title": "Question",
            "description": "The question text"
          },
          "answer": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Answer",
            "description": "Expanded answer text, if available"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Answer source URL"
          }
        },
        "type": "object",
        "required": [
          "question"
        ],
        "title": "SerpPAAQuestion",
        "description": "A 'People Also Ask' question."
      },
      "SerpRequest": {
        "properties": {
          "query": {
            "type": "string",
            "maxLength": 500,
            "minLength": 1,
            "title": "Query",
            "description": "Search query (max 500 characters)"
          },
          "search_engine": {
            "type": "string",
            "enum": [
              "google",
              "bing"
            ],
            "title": "Search Engine",
            "description": "Target search engine. Google is the primary target for ad extraction.",
            "default": "google"
          },
          "device": {
            "type": "string",
            "enum": [
              "desktop",
              "mobile"
            ],
            "title": "Device",
            "description": "Device type to emulate. Affects SERP layout and ad placements. Desktop typically shows more ads.",
            "default": "desktop"
          },
          "country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "ISO 3166-1 alpha-2 country code for geo-targeted results (e.g. 'US', 'GB', 'DE'). Routes through a proxy in the specified country."
          },
          "city": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "City",
            "description": "City name for local ad targeting (e.g. 'London', 'New York'). Used with country for precise geo-targeting. Requires country to be set."
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5,
                "minLength": 2
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Language code for results and browser locale (e.g. 'en', 'de', 'fr')"
          },
          "num_results": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "title": "Num Results",
            "description": "Number of organic results to request (1-100). Google typically serves 10 per page.",
            "default": 10
          },
          "page": {
            "type": "integer",
            "maximum": 10.0,
            "minimum": 1.0,
            "title": "Page",
            "description": "Result page number (1-indexed). Page 2 = results 11-20.",
            "default": 1
          },
          "include_ads": {
            "type": "boolean",
            "title": "Include Ads",
            "description": "Extract ad data from the SERP. When false, only organic results are returned (faster, cheaper). Default true — the primary use case for this endpoint.",
            "default": true
          },
          "brand_domain": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 253
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand Domain",
            "description": "Brand domain to classify ads against (e.g. 'wayfair.com'). When provided, each ad gets an is_brand_ad classification: true if the ad's display domain matches this brand, false otherwise. When omitted, is_brand_ad is null for all ads (no classification). Provide the bare domain without protocol or path."
          },
          "resolve_redirects": {
            "type": "boolean",
            "title": "Resolve Redirects",
            "description": "Follow ad click-through redirect chains to resolve final landing URLs. Adds latency (~200-500ms per ad) but provides the actual destination URL. When false, only the Google tracking URL is captured.",
            "default": false
          },
          "solve_captchas": {
            "type": "boolean",
            "title": "Solve Captchas",
            "description": "Whether to solve CAPTCHAs transparently when Google presents a reCAPTCHA challenge. When True (default), CAPTCHAs are solved automatically and results are returned — the customer sees slightly higher latency but no errors. When False, CAPTCHA pages are treated as blocks and the request may fail or fall back to another engine. Disable to avoid the added latency on latency-sensitive workloads where a retry is acceptable.",
            "default": true
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "Reuse a long-lived browser session for consistent fingerprinting across multiple searches. Obtain a session_id from the Session Pool API. When omitted, a one-shot session is used."
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL for async delivery. When set, the API returns 202 immediately and POSTs the full SerpResponse to this URL when complete."
          },
          "webhook_secret": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256,
                "minLength": 8
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Secret",
            "description": "Secret for HMAC-SHA256 webhook signature verification. When provided, the webhook POST includes an X-AlterLab-Signature header containing sha256=<hex_digest> computed over the JSON payload body."
          }
        },
        "type": "object",
        "required": [
          "query"
        ],
        "title": "SerpRequest",
        "description": "Request body for POST /v1/serp.\n\nScrapes a Google (or Bing) SERP page using browser-tier rendering to capture\nads, organic results, and rich result data. Designed for B2B ad intelligence\nworkflows where ad visibility and structured extraction are critical."
      },
      "SerpResponse": {
        "properties": {
          "serp_id": {
            "type": "string",
            "title": "Serp Id",
            "description": "Unique identifier for this SERP request"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query that was executed"
          },
          "search_engine": {
            "type": "string",
            "title": "Search Engine",
            "description": "Search engine used (google/bing)"
          },
          "device": {
            "type": "string",
            "title": "Device",
            "description": "Device type used (desktop/mobile)"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Geo-target country used"
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "Language used"
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Id",
            "description": "Session ID used (if long-lived session)"
          },
          "organic_results": {
            "items": {
              "$ref": "#/components/schemas/SerpOrganicResult"
            },
            "type": "array",
            "title": "Organic Results",
            "description": "Organic (non-paid) search results"
          },
          "organic_count": {
            "type": "integer",
            "title": "Organic Count",
            "description": "Number of organic results returned",
            "default": 0
          },
          "ads": {
            "items": {
              "$ref": "#/components/schemas/SerpAdResult"
            },
            "type": "array",
            "title": "Ads",
            "description": "Paid ad results extracted from the SERP. Includes top ads, bottom ads, and shopping ads. Empty when include_ads=false."
          },
          "ads_count": {
            "type": "integer",
            "title": "Ads Count",
            "description": "Total number of ads found on the SERP",
            "default": 0
          },
          "ads_by_placement": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Ads By Placement",
            "description": "Ad count by placement: {'top': N, 'bottom': N, 'sidebar': N, 'shopping': N}"
          },
          "competitive_metrics": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpCompetitiveMetrics"
              },
              {
                "type": "null"
              }
            ],
            "description": "Derived competitive intelligence metrics computed from ad data. Null when include_ads=false or no ads are present."
          },
          "featured_snippet": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpFeaturedSnippet"
              },
              {
                "type": "null"
              }
            ],
            "description": "Featured snippet / answer box if present"
          },
          "knowledge_panel": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpKnowledgePanel"
              },
              {
                "type": "null"
              }
            ],
            "description": "Knowledge panel / entity card if present"
          },
          "people_also_ask": {
            "items": {
              "$ref": "#/components/schemas/SerpPAAQuestion"
            },
            "type": "array",
            "title": "People Also Ask",
            "description": "'People Also Ask' questions"
          },
          "related_searches": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Related Searches",
            "description": "Related search query suggestions"
          },
          "did_you_mean": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Did You Mean",
            "description": "Search query correction suggestion"
          },
          "local_results": {
            "items": {
              "$ref": "#/components/schemas/SerpLocalResult"
            },
            "type": "array",
            "title": "Local Results",
            "description": "Local pack results"
          },
          "video_results": {
            "items": {
              "$ref": "#/components/schemas/SerpVideoResult"
            },
            "type": "array",
            "title": "Video Results",
            "description": "Video carousel results"
          },
          "news_results": {
            "items": {
              "$ref": "#/components/schemas/SerpNewsResult"
            },
            "type": "array",
            "title": "News Results",
            "description": "News carousel results"
          },
          "image_results": {
            "items": {
              "$ref": "#/components/schemas/SerpImageResult"
            },
            "type": "array",
            "title": "Image Results",
            "description": "Image carousel results"
          },
          "shopping_results": {
            "items": {
              "$ref": "#/components/schemas/SerpShoppingResult"
            },
            "type": "array",
            "title": "Shopping Results",
            "description": "Shopping carousel results (organic, not paid ads)"
          },
          "estimated_total_results": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Estimated Total Results",
            "description": "Estimated total results from the search engine"
          },
          "cost_breakdown": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpCostBreakdown"
              },
              {
                "type": "null"
              }
            ],
            "description": "Cost breakdown for this request"
          },
          "captcha_stats": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Captcha Stats",
            "description": "CAPTCHA solving statistics for this request. Populated when solve_captchas=true and at least one CAPTCHA was encountered. Keys: captchas_encountered (int), captchas_solved (int), captchas_failed (int), total_solve_time_ms (float)."
          },
          "latency_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Latency Ms",
            "description": "Total request latency in milliseconds"
          }
        },
        "type": "object",
        "required": [
          "serp_id",
          "query",
          "search_engine",
          "device"
        ],
        "title": "SerpResponse",
        "description": "Response from POST /v1/serp.\n\nContains organic results, ad results (when include_ads=true), and rich\nresult data from the SERP page."
      },
      "SerpSessionCreateRequest": {
        "properties": {
          "geo": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 8
              },
              {
                "type": "null"
              }
            ],
            "title": "Geo",
            "description": "ISO 3166-1 alpha-2 country code for geo-targeted results (e.g. 'US', 'GB', 'DE'). When provided, the session will be labelled with this geo for informational purposes. Actual proxy geo selection is handled by the worker session pool."
          }
        },
        "type": "object",
        "title": "SerpSessionCreateRequest",
        "description": "Request body for POST /v1/serp/sessions — create a named persistent session."
      },
      "SerpSessionCreateResponse": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id",
            "description": "Session identifier — pass as session_id in future SERP scrape requests"
          },
          "state": {
            "type": "string",
            "title": "State",
            "description": "Current session state (typically 'active')"
          },
          "geo": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Geo",
            "description": "Requested geo label, or null"
          },
          "created_at": {
            "type": "string",
            "title": "Created At",
            "description": "ISO 8601 timestamp when the session was registered"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "description": "Human-readable status message",
            "default": "Session registered. Use session_id in POST /v1/serp to reuse this session."
          },
          "worker_hint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Worker Hint",
            "description": "Worker instance identifier that owns this session. Informational — the API automatically routes requests with this session_id to the correct worker via session affinity (#19780). Null if worker registry is unavailable."
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "state",
          "created_at"
        ],
        "title": "SerpSessionCreateResponse",
        "description": "Response from POST /v1/serp/sessions — newly registered session."
      },
      "SerpSessionInfo": {
        "properties": {
          "session_id": {
            "type": "string",
            "title": "Session Id",
            "description": "Opaque session identifier — pass as session_id in scrape requests"
          },
          "state": {
            "type": "string",
            "title": "State",
            "description": "Session lifecycle state: warming, active, degraded, rotating, retired"
          },
          "geo": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Geo",
            "description": "Requested geo (ISO 3166-1 alpha-2) when session was created, or null"
          },
          "search_count": {
            "type": "integer",
            "title": "Search Count",
            "description": "Total searches completed in this session"
          },
          "block_count": {
            "type": "integer",
            "title": "Block Count",
            "description": "Number of searches blocked by Google"
          },
          "success_count": {
            "type": "integer",
            "title": "Success Count",
            "description": "Number of searches that returned results"
          },
          "block_rate": {
            "type": "number",
            "title": "Block Rate",
            "description": "Fraction of searches blocked (0.0–1.0)"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "description": "Fraction of searches that succeeded (0.0–1.0)"
          },
          "age_s": {
            "type": "number",
            "title": "Age S",
            "description": "Session age in seconds since creation"
          },
          "idle_s": {
            "type": "number",
            "title": "Idle S",
            "description": "Seconds since this session last handled a search"
          },
          "browser_healthy": {
            "type": "boolean",
            "title": "Browser Healthy",
            "description": "Whether the underlying Chrome process is still connected"
          },
          "created_at": {
            "type": "string",
            "title": "Created At",
            "description": "ISO 8601 timestamp when this session was registered by the user"
          }
        },
        "type": "object",
        "required": [
          "session_id",
          "state",
          "search_count",
          "block_count",
          "success_count",
          "block_rate",
          "success_rate",
          "age_s",
          "idle_s",
          "browser_healthy",
          "created_at"
        ],
        "title": "SerpSessionInfo",
        "description": "Health summary for a single persistent SERP session."
      },
      "SerpSessionListResponse": {
        "properties": {
          "sessions": {
            "items": {
              "$ref": "#/components/schemas/SerpSessionInfo"
            },
            "type": "array",
            "title": "Sessions",
            "description": "Sessions registered by the authenticated user"
          },
          "total": {
            "type": "integer",
            "title": "Total",
            "description": "Total number of sessions returned"
          }
        },
        "type": "object",
        "required": [
          "sessions",
          "total"
        ],
        "title": "SerpSessionListResponse",
        "description": "Response from GET /v1/serp/sessions — list of active user sessions."
      },
      "SerpShoppingResult": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Product title"
          },
          "price": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Price",
            "description": "Price string (e.g. '$29.99')"
          },
          "merchant": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Merchant",
            "description": "Merchant / seller name"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image Url",
            "description": "Product image URL"
          },
          "link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Link",
            "description": "Product page URL"
          },
          "rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating",
            "description": "Star rating (1-5)"
          },
          "review_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Count",
            "description": "Number of reviews"
          }
        },
        "type": "object",
        "required": [
          "title"
        ],
        "title": "SerpShoppingResult",
        "description": "A shopping result from the Google Shopping carousel (organic, not paid)."
      },
      "SerpSitelink": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Sitelink title"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Sitelink URL"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "SerpSitelink",
        "description": "A sitelink shown under an organic result."
      },
      "SerpSnapshotSummary": {
        "properties": {
          "snapshot_id": {
            "type": "string",
            "title": "Snapshot Id",
            "description": "Unique snapshot identifier"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "title": "Timestamp",
            "description": "When this snapshot was captured"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query"
          },
          "search_engine": {
            "type": "string",
            "title": "Search Engine",
            "description": "Search engine used"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country",
            "description": "Country code"
          },
          "device": {
            "type": "string",
            "title": "Device",
            "description": "Device type"
          },
          "ads_count": {
            "type": "integer",
            "title": "Ads Count",
            "description": "Number of ads in this snapshot"
          },
          "organic_count": {
            "type": "integer",
            "title": "Organic Count",
            "description": "Number of organic results"
          },
          "top_advertisers": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Top Advertisers",
            "description": "Top advertiser domains from ads in this snapshot"
          },
          "competitive_metrics": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Competitive Metrics",
            "description": "Competitive intelligence metrics for this snapshot"
          },
          "is_duplicate": {
            "type": "boolean",
            "title": "Is Duplicate",
            "description": "Whether this snapshot was identical to the previous one (deduplicated)",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "snapshot_id",
          "timestamp",
          "query",
          "search_engine",
          "device",
          "ads_count",
          "organic_count"
        ],
        "title": "SerpSnapshotSummary",
        "description": "A single SERP snapshot in the history timeline."
      },
      "SerpStatusResponse": {
        "properties": {
          "serp_id": {
            "type": "string",
            "title": "Serp Id",
            "description": "SERP request identifier"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "failed"
            ],
            "title": "Status",
            "description": "Current status of the SERP request"
          },
          "query": {
            "type": "string",
            "title": "Query",
            "description": "The search query"
          },
          "result": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SerpResponse"
              },
              {
                "type": "null"
              }
            ],
            "description": "Full SERP response (populated when status='completed')"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error",
            "description": "Error message (populated when status='failed')"
          }
        },
        "type": "object",
        "required": [
          "serp_id",
          "status",
          "query"
        ],
        "title": "SerpStatusResponse",
        "description": "Response from GET /v1/serp/{serp_id} — poll for async SERP results."
      },
      "SerpVideoResult": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Video title"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Video URL"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Video platform (e.g. 'YouTube')"
          },
          "duration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration",
            "description": "Duration string"
          },
          "thumbnail_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thumbnail Url",
            "description": "Thumbnail image URL"
          },
          "date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date",
            "description": "Upload/publish date"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "SerpVideoResult",
        "description": "A video result from the video carousel."
      },
      "ServiceAccountKeyCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Descriptive name for the key"
          },
          "ip_allowlist": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Allowlist",
            "description": "Optional list of CIDR ranges or single IPs allowed to use this key. Empty list or null means unrestricted. Example: ['203.0.113.0/24', '198.51.100.5']."
          },
          "replaces_key_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Replaces Key Id",
            "description": "UUID of an existing service account key to atomically deactivate when this new key is created. Enables zero-downtime key rotation."
          },
          "scopes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scopes",
            "description": "Optional list of permission scopes for this key. Allowed values: 'scrape', 'b2b:write', 'b2b:read', 'b2b:delivery'. Defaults to ['scrape'] when omitted."
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "ServiceAccountKeyCreate",
        "description": "Request body for creating a service account (M2M) API key.\n\nService account keys are scoped to the organisation, not a user account.\nThey support IP allowlists for network-layer access control and zero-downtime\nkey rotation via ``replaces_key_id``."
      },
      "ServiceStatus": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "latency_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Latency Ms"
          }
        },
        "type": "object",
        "required": [
          "name",
          "status"
        ],
        "title": "ServiceStatus",
        "description": "Individual service status for public status page."
      },
      "SessionAlertPreferences": {
        "properties": {
          "email_on_new_ip": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email On New Ip",
            "description": "Email when session accessed from a new IP"
          },
          "email_on_unusual_volume": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email On Unusual Volume",
            "description": "Email when usage volume is unusually high"
          },
          "email_on_every_use": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email On Every Use",
            "description": "Email on every session use (opt-in, high volume)"
          },
          "email_on_failure_streak": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email On Failure Streak",
            "description": "Email when session fails repeatedly"
          },
          "herald_alerts": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Herald Alerts",
            "description": "In-app (herald) notifications for all alert types"
          }
        },
        "type": "object",
        "title": "SessionAlertPreferences",
        "description": "Configurable alert preferences for session security notifications."
      },
      "SessionAlertPreferencesResponse": {
        "properties": {
          "email_on_new_ip": {
            "type": "boolean",
            "title": "Email On New Ip"
          },
          "email_on_unusual_volume": {
            "type": "boolean",
            "title": "Email On Unusual Volume"
          },
          "email_on_every_use": {
            "type": "boolean",
            "title": "Email On Every Use"
          },
          "email_on_failure_streak": {
            "type": "boolean",
            "title": "Email On Failure Streak"
          },
          "herald_alerts": {
            "type": "boolean",
            "title": "Herald Alerts"
          }
        },
        "type": "object",
        "required": [
          "email_on_new_ip",
          "email_on_unusual_volume",
          "email_on_every_use",
          "email_on_failure_streak",
          "herald_alerts"
        ],
        "title": "SessionAlertPreferencesResponse",
        "description": "Response for GET/PUT alert preferences."
      },
      "SessionAuditEntry": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "details": {
            "additionalProperties": true,
            "type": "object",
            "title": "Details"
          },
          "performed_by": {
            "type": "string",
            "format": "uuid",
            "title": "Performed By"
          },
          "performer_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Performer Name"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "action",
          "details",
          "performed_by",
          "created_at"
        ],
        "title": "SessionAuditEntry",
        "description": "Audit log entry for session operations."
      },
      "SessionAuditResponse": {
        "properties": {
          "entries": {
            "items": {
              "$ref": "#/components/schemas/SessionAuditEntry"
            },
            "type": "array",
            "title": "Entries"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "entries",
          "total"
        ],
        "title": "SessionAuditResponse",
        "description": "Response schema for session audit log."
      },
      "SessionAutoRefreshSettings": {
        "properties": {
          "auto_refresh_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Refresh Enabled"
          },
          "notify_before_expiry": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notify Before Expiry"
          },
          "notify_on_failure": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notify On Failure"
          }
        },
        "type": "object",
        "title": "SessionAutoRefreshSettings",
        "description": "Schema for updating auto-refresh preferences on a session."
      },
      "SessionCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "User label for this session"
          },
          "domain": {
            "type": "string",
            "maxLength": 255,
            "minLength": 3,
            "title": "Domain",
            "description": "Target domain (e.g. amazon.com)"
          },
          "cookies": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookies",
            "description": "Cookie data for server-side encryption. Either a {name: value} dict (legacy) or a list of cookie objects with metadata (name, value, domain, path, secure, httpOnly, sameSite, expires)."
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Optional custom headers for this session"
          },
          "encryption_mode": {
            "type": "string",
            "enum": [
              "server",
              "client"
            ],
            "title": "Encryption Mode",
            "description": "'server' (default) or 'client' (zero-knowledge)",
            "default": "server"
          },
          "encrypted_cookies": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Encrypted Cookies",
            "description": "Client-encrypted cookie blob: base64(iv).base64(ciphertext)"
          },
          "wrapped_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wrapped Key",
            "description": "RSA-OAEP wrapped AES-256 session key (base64)"
          },
          "cookie_names": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookie Names",
            "description": "Plaintext cookie names for UI display (no values)"
          },
          "key_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Version",
            "description": "RSA key version used for encryption"
          },
          "consent": {
            "type": "boolean",
            "title": "Consent",
            "description": "Explicit GDPR consent to process session cookie data. Must be true to create sessions.",
            "default": false
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At",
            "description": "When the session expires"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes",
            "description": "User notes"
          },
          "auto_refresh_enabled": {
            "type": "boolean",
            "title": "Auto Refresh Enabled",
            "description": "Enable proactive expiry detection and health checks",
            "default": true
          },
          "notify_before_expiry": {
            "type": "boolean",
            "title": "Notify Before Expiry",
            "description": "Send notification when session is about to expire",
            "default": true
          },
          "notify_on_failure": {
            "type": "boolean",
            "title": "Notify On Failure",
            "description": "Send notification when session validation fails",
            "default": true
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id",
            "description": "Organization to assign session to (org admins only)"
          },
          "shared": {
            "type": "boolean",
            "title": "Shared",
            "description": "Share with organization members immediately",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name",
          "domain"
        ],
        "title": "SessionCreate",
        "description": "Schema for creating a new session integration.\n\nSupports two modes:\n- Server-side encryption (default): Send plaintext cookies, server encrypts.\n- Client-side encryption (zero-knowledge): Send pre-encrypted blob + wrapped key.\n\nFor client-side: set encryption_mode=\"client\", provide encrypted_cookies,\nwrapped_key, and cookie_names instead of cookies."
      },
      "SessionDataExportResponse": {
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "exported_at": {
            "type": "string",
            "format": "date-time",
            "title": "Exported At"
          },
          "sessions": {
            "items": {
              "$ref": "#/components/schemas/SessionExportEntry"
            },
            "type": "array",
            "title": "Sessions"
          },
          "total_sessions": {
            "type": "integer",
            "title": "Total Sessions"
          },
          "data_processing_info": {
            "type": "string",
            "title": "Data Processing Info",
            "description": "Data processing description for GDPR transparency",
            "default": "AES-256-GCM encrypted at rest, stored in PostgreSQL and cached in Redis. Cookie values are domain-bound encrypted and never logged. Auto-deleted after 90 days of inactivity. Only the worker process decrypts cookies during scraping — no human access."
          }
        },
        "type": "object",
        "required": [
          "user_id",
          "exported_at",
          "sessions",
          "total_sessions"
        ],
        "title": "SessionDataExportResponse",
        "description": "Full GDPR data export for a user's session data."
      },
      "SessionExportEntry": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "cookie_names": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Cookie Names",
            "description": "Cookie names only — values are never exported"
          },
          "encryption_mode": {
            "type": "string",
            "title": "Encryption Mode"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests"
          },
          "consent_given_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Consent Given At"
          },
          "data_region": {
            "type": "string",
            "title": "Data Region",
            "default": "eu"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "domain",
          "cookie_names",
          "encryption_mode",
          "status",
          "created_at",
          "total_requests",
          "successful_requests"
        ],
        "title": "SessionExportEntry",
        "description": "A single session's data for GDPR data export (no cookie values)."
      },
      "SessionHealthCheckResult": {
        "properties": {
          "total_checked": {
            "type": "integer",
            "title": "Total Checked",
            "description": "Number of sessions evaluated"
          },
          "expiring_soon": {
            "type": "integer",
            "title": "Expiring Soon",
            "description": "Sessions expiring within 48 hours"
          },
          "already_expired": {
            "type": "integer",
            "title": "Already Expired",
            "description": "Sessions found to be expired"
          },
          "needs_revalidation": {
            "type": "integer",
            "title": "Needs Revalidation",
            "description": "Sessions flagged for revalidation"
          },
          "notifications_sent": {
            "type": "integer",
            "title": "Notifications Sent",
            "description": "Expiry notifications created"
          }
        },
        "type": "object",
        "required": [
          "total_checked",
          "expiring_soon",
          "already_expired",
          "needs_revalidation",
          "notifications_sent"
        ],
        "title": "SessionHealthCheckResult",
        "description": "Result of a periodic session health check run."
      },
      "SessionListResponse": {
        "properties": {
          "sessions": {
            "items": {
              "$ref": "#/components/schemas/app__schemas__session__SessionResponse"
            },
            "type": "array",
            "title": "Sessions"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "sessions",
          "total"
        ],
        "title": "SessionListResponse",
        "description": "Response schema for listing sessions."
      },
      "SessionProfileListResponse": {
        "properties": {
          "profiles": {
            "items": {
              "$ref": "#/components/schemas/SessionProfileSummary"
            },
            "type": "array",
            "title": "Profiles"
          },
          "categories": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Categories",
            "description": "Category slug to human-readable name mapping"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "profiles",
          "categories",
          "total"
        ],
        "title": "SessionProfileListResponse",
        "description": "Response for GET /sessions/profiles — all available profiles."
      },
      "SessionProfileResponse": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug",
            "description": "Unique profile identifier (e.g. 'amazon', 'reddit')"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name",
            "description": "Human-readable site name"
          },
          "category": {
            "type": "string",
            "title": "Category",
            "description": "Profile category (e-commerce, social, news, etc.)"
          },
          "icon": {
            "type": "string",
            "title": "Icon",
            "description": "Icon identifier for the frontend"
          },
          "domains": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Domains",
            "description": "All domain variants this profile covers"
          },
          "required_cookies": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Required Cookies",
            "description": "Cookies that MUST be present for the session to work"
          },
          "optional_cookies": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Optional Cookies",
            "description": "Cookies that improve quality but are not strictly required"
          },
          "capture_instructions": {
            "type": "string",
            "title": "Capture Instructions",
            "description": "Step-by-step guide for users to capture their cookies"
          },
          "min_tier": {
            "type": "integer",
            "title": "Min Tier",
            "description": "Recommended anti-bot tier for authenticated scraping"
          },
          "validation_url": {
            "type": "string",
            "title": "Validation Url",
            "description": "URL path to test if the session is logged in"
          },
          "logged_in_indicator": {
            "type": "string",
            "title": "Logged In Indicator",
            "description": "Text present on the validation page when authenticated"
          },
          "notes": {
            "type": "string",
            "title": "Notes",
            "description": "Additional tips or caveats for this site"
          }
        },
        "type": "object",
        "required": [
          "slug",
          "display_name",
          "category",
          "icon",
          "domains",
          "required_cookies",
          "optional_cookies",
          "capture_instructions",
          "min_tier",
          "validation_url",
          "logged_in_indicator",
          "notes"
        ],
        "title": "SessionProfileResponse",
        "description": "A pre-built session profile template for a popular site."
      },
      "SessionProfileSummary": {
        "properties": {
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "icon": {
            "type": "string",
            "title": "Icon"
          },
          "domains": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Domains"
          },
          "required_cookies": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Required Cookies"
          }
        },
        "type": "object",
        "required": [
          "slug",
          "display_name",
          "category",
          "icon",
          "domains",
          "required_cookies"
        ],
        "title": "SessionProfileSummary",
        "description": "Lightweight profile summary for list views (excludes instructions)."
      },
      "SessionRefreshRequest": {
        "properties": {
          "cookies": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookies",
            "description": "Cookie data — dict {name: value} or list of cookie objects with metadata"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Optional updated custom headers"
          },
          "encryption_mode": {
            "type": "string",
            "enum": [
              "server",
              "client"
            ],
            "title": "Encryption Mode",
            "description": "'server' (default) or 'client' (zero-knowledge)",
            "default": "server"
          },
          "encrypted_cookies": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Encrypted Cookies"
          },
          "wrapped_key": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wrapped Key"
          },
          "cookie_names": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookie Names"
          },
          "key_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Version"
          }
        },
        "type": "object",
        "title": "SessionRefreshRequest",
        "description": "Schema for refreshing (rotating) session cookies.\n\nSupports both server-side and client-side encryption modes.\nFor client-side: set encryption_mode=\"client\" with encrypted_cookies,\nwrapped_key, and cookie_names."
      },
      "SessionShareRequest": {
        "properties": {
          "organization_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id",
            "description": "Organization to share with. If null, uses the session's existing org."
          }
        },
        "type": "object",
        "title": "SessionShareRequest",
        "description": "Schema for sharing/unsharing a session with an organization."
      },
      "SessionUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "cookies": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookies",
            "description": "Cookie data — dict {name: value} or list of cookie objects with metadata"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 1000
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "auto_refresh_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Refresh Enabled",
            "description": "Enable/disable proactive expiry detection"
          },
          "notify_before_expiry": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notify Before Expiry",
            "description": "Enable/disable pre-expiry notifications"
          },
          "notify_on_failure": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notify On Failure",
            "description": "Enable/disable failure notifications"
          }
        },
        "type": "object",
        "title": "SessionUpdate",
        "description": "Schema for updating a session integration."
      },
      "SessionValidationResult": {
        "properties": {
          "is_valid": {
            "type": "boolean",
            "title": "Is Valid"
          },
          "confidence": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "title": "Confidence",
            "description": "Confidence score 0-100",
            "default": 0
          },
          "http_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Http Status"
          },
          "detected_user": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Detected User",
            "description": "Detected logged-in username if available"
          },
          "cookie_expiry_detected": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cookie Expiry Detected"
          },
          "cookies_expiring_soon": {
            "type": "boolean",
            "title": "Cookies Expiring Soon",
            "description": "True if any cookie expires within 24 hours",
            "default": false
          },
          "indicators_found": {
            "anyOf": [
              {
                "additionalProperties": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Indicators Found",
            "description": "Logged-in and logged-out indicators found in response"
          },
          "consecutive_failures": {
            "type": "integer",
            "title": "Consecutive Failures",
            "description": "Number of consecutive validation failures",
            "default": 0
          },
          "details": {
            "type": "string",
            "title": "Details"
          }
        },
        "type": "object",
        "required": [
          "is_valid",
          "details"
        ],
        "title": "SessionValidationResult",
        "description": "Result of a session validation check."
      },
      "SetDefaultOrganizationRequest": {
        "properties": {
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          }
        },
        "type": "object",
        "required": [
          "organization_id"
        ],
        "title": "SetDefaultOrganizationRequest",
        "description": "Set user's default organization."
      },
      "SetupIntentResponse": {
        "properties": {
          "client_secret": {
            "type": "string",
            "title": "Client Secret"
          },
          "id": {
            "type": "string",
            "title": "Id"
          }
        },
        "type": "object",
        "required": [
          "client_secret",
          "id"
        ],
        "title": "SetupIntentResponse",
        "description": "Response containing Setup Intent client secret for Stripe.js."
      },
      "ShareResourceResponse": {
        "properties": {
          "resource_type": {
            "type": "string",
            "title": "Resource Type"
          },
          "resource_id": {
            "type": "string",
            "format": "uuid",
            "title": "Resource Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Resource shared to workspace"
          }
        },
        "type": "object",
        "required": [
          "resource_type",
          "resource_id",
          "organization_id"
        ],
        "title": "ShareResourceResponse",
        "description": "Returned after successfully sharing a resource to an org workspace."
      },
      "SharedContactListItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "contact_count": {
            "type": "integer",
            "title": "Contact Count",
            "default": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "organization_id",
          "name",
          "created_at",
          "updated_at"
        ],
        "title": "SharedContactListItem",
        "description": "A contact list shared to a workspace."
      },
      "SharedContactListListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SharedContactListItem"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total"
        ],
        "title": "SharedContactListListResponse"
      },
      "SharedSecretItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "masked_preview": {
            "type": "string",
            "title": "Masked Preview"
          },
          "integration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Integration"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "organization_id",
          "name",
          "masked_preview",
          "created_at",
          "updated_at"
        ],
        "title": "SharedSecretItem",
        "description": "A secret shared to a workspace.\n\nOnly ``masked_preview`` is exposed — the encrypted value is never returned."
      },
      "SharedSecretListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SharedSecretItem"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total"
        ],
        "title": "SharedSecretListResponse"
      },
      "SharedWorkflowItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "organization_id": {
            "type": "string",
            "format": "uuid",
            "title": "Organization Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "organization_id",
          "name",
          "status",
          "run_count",
          "created_at",
          "updated_at"
        ],
        "title": "SharedWorkflowItem",
        "description": "A workflow shared to a workspace."
      },
      "SharedWorkflowListResponse": {
        "properties": {
          "items": {
            "items": {
              "$ref": "#/components/schemas/SharedWorkflowItem"
            },
            "type": "array",
            "title": "Items"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "items",
          "total"
        ],
        "title": "SharedWorkflowListResponse"
      },
      "ShoppingResultResponse": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Product title"
          },
          "price": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Price",
            "description": "Price string (e.g. '$29.99')"
          },
          "merchant": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Merchant",
            "description": "Merchant / seller name"
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image Url",
            "description": "Product image URL"
          },
          "link": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Link",
            "description": "Product page URL"
          },
          "rating": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rating",
            "description": "Star rating (1-5)"
          },
          "review_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Review Count",
            "description": "Number of reviews"
          }
        },
        "type": "object",
        "required": [
          "title"
        ],
        "title": "ShoppingResultResponse",
        "description": "A shopping result from the Google Shopping carousel."
      },
      "SitelinkResponse": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Sitelink title"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Sitelink URL"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "SitelinkResponse",
        "description": "A sitelink shown under a search result."
      },
      "SnapshotDetailResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "run_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Run Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "content_hash": {
            "type": "string",
            "title": "Content Hash"
          },
          "content": {
            "additionalProperties": true,
            "type": "object",
            "title": "Content"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "url",
          "content_hash",
          "content",
          "created_at"
        ],
        "title": "SnapshotDetailResponse",
        "description": "Monitor snapshot with content."
      },
      "SnapshotListResponse": {
        "properties": {
          "snapshots": {
            "items": {
              "$ref": "#/components/schemas/SnapshotResponse"
            },
            "type": "array",
            "title": "Snapshots"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "snapshots",
          "total"
        ],
        "title": "SnapshotListResponse",
        "description": "List of snapshots."
      },
      "SnapshotResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "schedule_id": {
            "type": "string",
            "format": "uuid",
            "title": "Schedule Id"
          },
          "run_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Run Id"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "content_hash": {
            "type": "string",
            "title": "Content Hash"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "schedule_id",
          "url",
          "content_hash",
          "created_at"
        ],
        "title": "SnapshotResponse",
        "description": "Monitor snapshot."
      },
      "SpendLimitConfig": {
        "properties": {
          "budget_limit_microcents": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget Limit Microcents",
            "description": "Budget cap in microcents (1,000,000 = $1.00). null = no budget limit."
          },
          "request_limit": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Limit",
            "description": "Max requests per period. null = no request limit."
          },
          "reset_period": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ],
            "title": "Reset Period",
            "description": "How often the counters reset.",
            "default": "monthly"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Whether this limit is active.",
            "default": true
          }
        },
        "type": "object",
        "title": "SpendLimitConfig",
        "description": "Configuration for a spend limit (shared between key and account)."
      },
      "SpendLimitStatus": {
        "properties": {
          "budget_limit_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget Limit Microcents"
          },
          "request_limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Request Limit"
          },
          "reset_period": {
            "type": "string",
            "title": "Reset Period",
            "default": "monthly"
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          },
          "current_spend_microcents": {
            "type": "integer",
            "title": "Current Spend Microcents",
            "default": 0
          },
          "current_request_count": {
            "type": "integer",
            "title": "Current Request Count",
            "default": 0
          },
          "current_period_start": {
            "type": "string",
            "format": "date-time",
            "title": "Current Period Start"
          },
          "resets_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resets At"
          },
          "budget_percent_used": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Budget Percent Used",
            "description": "Percentage of budget used (0-100)."
          },
          "requests_percent_used": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requests Percent Used",
            "description": "Percentage of request limit used (0-100)."
          }
        },
        "type": "object",
        "required": [
          "current_period_start"
        ],
        "title": "SpendLimitStatus",
        "description": "Current status of a spend limit."
      },
      "StatusCodeItem": {
        "properties": {
          "code": {
            "type": "string",
            "title": "Code"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "percentage": {
            "type": "number",
            "title": "Percentage"
          }
        },
        "type": "object",
        "required": [
          "code",
          "requests",
          "percentage"
        ],
        "title": "StatusCodeItem",
        "description": "Status code data item."
      },
      "StatusCodeResponse": {
        "properties": {
          "individual": {
            "items": {
              "$ref": "#/components/schemas/StatusCodeItem"
            },
            "type": "array",
            "title": "Individual"
          },
          "grouped": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Grouped"
          }
        },
        "type": "object",
        "required": [
          "individual",
          "grouped"
        ],
        "title": "StatusCodeResponse",
        "description": "Status code distribution response."
      },
      "StorageIntegrationCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Friendly name (e.g., 'My S3 Bucket')",
            "examples": [
              "My S3 Bucket"
            ]
          },
          "provider": {
            "$ref": "#/components/schemas/StorageProvider",
            "description": "Cloud storage provider"
          },
          "credentials": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Credentials",
            "description": "Provider-specific credentials"
          },
          "bucket": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Bucket",
            "description": "Bucket or container name"
          },
          "region": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Region",
            "description": "AWS region, GCS location, or Azure region"
          },
          "prefix": {
            "type": "string",
            "maxLength": 500,
            "title": "Prefix",
            "description": "Default key prefix for uploads",
            "default": ""
          },
          "is_default": {
            "type": "boolean",
            "title": "Is Default",
            "description": "Set as default export destination",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name",
          "provider",
          "credentials",
          "bucket"
        ],
        "title": "StorageIntegrationCreate",
        "description": "Create a new storage integration."
      },
      "StorageIntegrationCredentialsUpdate": {
        "properties": {
          "credentials": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Credentials",
            "description": "New provider-specific credentials"
          }
        },
        "type": "object",
        "required": [
          "credentials"
        ],
        "title": "StorageIntegrationCredentialsUpdate",
        "description": "Update credentials for an existing storage integration."
      },
      "StorageIntegrationListResponse": {
        "properties": {
          "integrations": {
            "items": {
              "$ref": "#/components/schemas/StorageIntegrationResponse"
            },
            "type": "array",
            "title": "Integrations"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "integrations",
          "total"
        ],
        "title": "StorageIntegrationListResponse",
        "description": "List of storage integrations."
      },
      "StorageIntegrationResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "provider": {
            "$ref": "#/components/schemas/StorageProvider"
          },
          "bucket": {
            "type": "string",
            "title": "Bucket"
          },
          "region": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Region"
          },
          "prefix": {
            "type": "string",
            "title": "Prefix"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "is_default": {
            "type": "boolean",
            "title": "Is Default"
          },
          "validation_status": {
            "$ref": "#/components/schemas/ValidationStatus"
          },
          "last_validated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Validated At"
          },
          "validation_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Validation Error"
          },
          "total_exports": {
            "type": "integer",
            "title": "Total Exports"
          },
          "successful_exports": {
            "type": "integer",
            "title": "Successful Exports"
          },
          "failed_exports": {
            "type": "integer",
            "title": "Failed Exports"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "total_bytes_uploaded": {
            "type": "integer",
            "title": "Total Bytes Uploaded"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "provider",
          "bucket",
          "prefix",
          "is_active",
          "is_default",
          "validation_status",
          "total_exports",
          "successful_exports",
          "failed_exports",
          "success_rate",
          "total_bytes_uploaded",
          "created_at",
          "updated_at"
        ],
        "title": "StorageIntegrationResponse",
        "description": "Storage integration details (never exposes credentials)."
      },
      "StorageIntegrationTestResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "title": "StorageIntegrationTestResponse",
        "description": "Response from storage integration test."
      },
      "StorageIntegrationUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "bucket": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Bucket"
          },
          "region": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Region"
          },
          "prefix": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Prefix"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          },
          "is_default": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Default"
          }
        },
        "type": "object",
        "title": "StorageIntegrationUpdate",
        "description": "Update an existing storage integration."
      },
      "StorageIntegrationValidateResponse": {
        "properties": {
          "valid": {
            "type": "boolean",
            "title": "Valid"
          },
          "provider": {
            "$ref": "#/components/schemas/StorageProvider"
          },
          "bucket_exists": {
            "type": "boolean",
            "title": "Bucket Exists",
            "default": false
          },
          "writable": {
            "type": "boolean",
            "title": "Writable",
            "default": false
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "valid",
          "provider"
        ],
        "title": "StorageIntegrationValidateResponse",
        "description": "Response from credential validation."
      },
      "StorageProvider": {
        "type": "string",
        "enum": [
          "s3",
          "gcs",
          "azure"
        ],
        "title": "StorageProvider",
        "description": "Supported cloud storage providers."
      },
      "StorageProviderInfo": {
        "properties": {
          "id": {
            "$ref": "#/components/schemas/StorageProvider"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "type": "string",
            "title": "Description"
          },
          "icon": {
            "type": "string",
            "title": "Icon"
          },
          "credential_fields": {
            "items": {
              "$ref": "#/components/schemas/CredentialField"
            },
            "type": "array",
            "title": "Credential Fields",
            "default": []
          },
          "requires_region": {
            "type": "boolean",
            "title": "Requires Region",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "icon"
        ],
        "title": "StorageProviderInfo",
        "description": "Information about a storage provider (for UI display)."
      },
      "StorefrontResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "display_name": {
            "type": "string",
            "title": "Display Name"
          },
          "bio": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Bio"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "accent_color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Accent Color"
          },
          "is_published": {
            "type": "boolean",
            "title": "Is Published"
          },
          "custom_domain": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Domain"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "user_id",
          "slug",
          "display_name",
          "bio",
          "logo_url",
          "accent_color",
          "is_published",
          "custom_domain",
          "created_at",
          "updated_at"
        ],
        "title": "StorefrontResponse",
        "description": "Authenticated creator view of their own storefront."
      },
      "StorefrontTemplateItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "price_cents": {
            "type": "integer",
            "title": "Price Cents"
          },
          "is_paid": {
            "type": "boolean",
            "title": "Is Paid"
          },
          "fork_count": {
            "type": "integer",
            "title": "Fork Count"
          },
          "review_count": {
            "type": "integer",
            "title": "Review Count"
          },
          "avg_rating": {
            "type": "number",
            "title": "Avg Rating"
          },
          "use_count": {
            "type": "integer",
            "title": "Use Count"
          },
          "is_featured": {
            "type": "boolean",
            "title": "Is Featured"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "category",
          "tags",
          "price_cents",
          "is_paid",
          "fork_count",
          "review_count",
          "avg_rating",
          "use_count",
          "is_featured"
        ],
        "title": "StorefrontTemplateItem",
        "description": "Minimal template summary for the public storefront listing."
      },
      "StorefrontUpsertRequest": {
        "properties": {
          "slug": {
            "type": "string",
            "maxLength": 64,
            "minLength": 2,
            "title": "Slug",
            "description": "URL-safe identifier (used in /s/{slug}). Alphanumeric and hyphens only. Application normalises via python-slugify."
          },
          "display_name": {
            "type": "string",
            "maxLength": 120,
            "minLength": 1,
            "title": "Display Name",
            "description": "Creator display name shown on the storefront page."
          },
          "bio": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Bio",
            "description": "Short description about the creator."
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url",
            "description": "Absolute URL for the creator's logo (http/https only)."
          },
          "accent_color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Accent Color",
            "description": "CSS hex color used as the storefront accent (e.g. '#3b82f6')."
          },
          "is_published": {
            "type": "boolean",
            "title": "Is Published",
            "description": "When True the storefront is visible at /s/{slug}.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "slug",
          "display_name"
        ],
        "title": "StorefrontUpsertRequest",
        "description": "PUT /creator/storefront — create or update the caller's storefront."
      },
      "SubscribeRequest": {
        "properties": {
          "success_url": {
            "type": "string",
            "minLength": 1,
            "format": "uri",
            "title": "Success Url",
            "description": "URL to redirect to after successful subscription"
          },
          "cancel_url": {
            "type": "string",
            "minLength": 1,
            "format": "uri",
            "title": "Cancel Url",
            "description": "URL to redirect to if subscriber cancels checkout"
          }
        },
        "type": "object",
        "required": [
          "success_url",
          "cancel_url"
        ],
        "title": "SubscribeRequest",
        "description": "POST /creator/subscribe/{plan_id} request body."
      },
      "SubscribeResponse": {
        "properties": {
          "checkout_url": {
            "type": "string",
            "title": "Checkout Url"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Complete payment on Stripe to activate your subscription."
          }
        },
        "type": "object",
        "required": [
          "checkout_url"
        ],
        "title": "SubscribeResponse",
        "description": "POST /creator/subscribe/{plan_id} response."
      },
      "SubscriberTrendPoint": {
        "properties": {
          "month": {
            "type": "string",
            "title": "Month"
          },
          "new_subscribers": {
            "type": "integer",
            "title": "New Subscribers"
          },
          "churned": {
            "type": "integer",
            "title": "Churned"
          },
          "net": {
            "type": "integer",
            "title": "Net"
          }
        },
        "type": "object",
        "required": [
          "month",
          "new_subscribers",
          "churned",
          "net"
        ],
        "title": "SubscriberTrendPoint",
        "description": "One month of subscriber growth data."
      },
      "SubscriptionMetricsResponse": {
        "properties": {
          "subscriber_count": {
            "type": "integer",
            "title": "Subscriber Count"
          },
          "mrr_cents": {
            "type": "integer",
            "title": "Mrr Cents"
          },
          "ltv_cents": {
            "type": "integer",
            "title": "Ltv Cents"
          },
          "churn_rate_pct": {
            "type": "number",
            "title": "Churn Rate Pct"
          },
          "plans": {
            "items": {},
            "type": "array",
            "title": "Plans"
          }
        },
        "type": "object",
        "required": [
          "subscriber_count",
          "mrr_cents",
          "ltv_cents",
          "churn_rate_pct",
          "plans"
        ],
        "title": "SubscriptionMetricsResponse",
        "description": "GET /creator/subscription-metrics response."
      },
      "SupportPreferencesPatchRequest": {
        "properties": {
          "email_admin_reply": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email Admin Reply",
            "description": "Override email_admin_reply; omit to leave unchanged"
          },
          "email_status_change": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email Status Change",
            "description": "Override email_status_change; omit to leave unchanged"
          },
          "email_resolved": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email Resolved",
            "description": "Override email_resolved; omit to leave unchanged"
          }
        },
        "type": "object",
        "title": "SupportPreferencesPatchRequest",
        "description": "Payload for PATCH /api/v1/support/preferences.\n\nSend only the notification_settings keys you want to change.\nUnknown keys are silently ignored to allow forward compatibility."
      },
      "SupportPreferencesResponse": {
        "properties": {
          "user_id": {
            "type": "string",
            "format": "uuid",
            "title": "User Id"
          },
          "notification_settings": {
            "$ref": "#/components/schemas/NotificationSettingsSchema"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "user_id",
          "notification_settings",
          "updated_at"
        ],
        "title": "SupportPreferencesResponse",
        "description": "Response for GET /api/v1/support/preferences.\n\nReturns the authenticated user's notification preferences. A preferences\nrow is created with defaults on the first GET if it doesn't yet exist."
      },
      "TemplateItem": {
        "properties": {
          "id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Id",
            "description": "UUID for user templates; null for built-in"
          },
          "name": {
            "type": "string",
            "title": "Name",
            "description": "Template name / identifier"
          },
          "description": {
            "type": "string",
            "title": "Description",
            "description": "Human-readable description of what the template extracts"
          },
          "schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Schema",
            "description": "JSON Schema for the extracted output"
          },
          "builtin": {
            "type": "boolean",
            "title": "Builtin",
            "description": "True for built-in templates, False for user-saved"
          }
        },
        "type": "object",
        "required": [
          "name",
          "description",
          "builtin"
        ],
        "title": "TemplateItem",
        "description": "A single extraction template (built-in or user-saved)."
      },
      "TemplateListResponse": {
        "properties": {
          "templates": {
            "items": {
              "$ref": "#/components/schemas/TemplateItem"
            },
            "type": "array",
            "title": "Templates"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "templates",
          "total"
        ],
        "title": "TemplateListResponse",
        "description": "Response for GET /v1/extract/templates."
      },
      "TemplateReviewCreate": {
        "properties": {
          "rating": {
            "type": "integer",
            "maximum": 5.0,
            "minimum": 1.0,
            "title": "Rating",
            "description": "Star rating (1–5)"
          },
          "body": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 5000
              },
              {
                "type": "null"
              }
            ],
            "title": "Body",
            "description": "Optional review text"
          }
        },
        "type": "object",
        "required": [
          "rating"
        ],
        "title": "TemplateReviewCreate",
        "description": "POST /workflows/templates/{id}/reviews body."
      },
      "TemplateReviewItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "reviewer_id": {
            "type": "string",
            "format": "uuid",
            "title": "Reviewer Id"
          },
          "rating": {
            "type": "integer",
            "title": "Rating"
          },
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Body"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "reviewer_id",
          "rating",
          "body",
          "created_at"
        ],
        "title": "TemplateReviewItem",
        "description": "A single review in the listing."
      },
      "TemplateReviewListResponse": {
        "properties": {
          "reviews": {
            "items": {
              "$ref": "#/components/schemas/TemplateReviewItem"
            },
            "type": "array",
            "title": "Reviews"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "avg_rating": {
            "type": "number",
            "title": "Avg Rating"
          },
          "review_count": {
            "type": "integer",
            "title": "Review Count"
          }
        },
        "type": "object",
        "required": [
          "reviews",
          "total",
          "avg_rating",
          "review_count"
        ],
        "title": "TemplateReviewListResponse",
        "description": "GET /workflows/templates/{id}/reviews response."
      },
      "TenantConfig": {
        "properties": {
          "rate_limit_override": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigRateLimitOverride"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_pricing": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigCustomPricing"
              },
              {
                "type": "null"
              }
            ]
          },
          "mfa_required": {
            "type": "boolean",
            "title": "Mfa Required",
            "default": false
          },
          "sso_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigSSOConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "api_key_audit_enabled": {
            "type": "boolean",
            "title": "Api Key Audit Enabled",
            "default": false
          },
          "delivery_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigDeliveryConfig"
              },
              {
                "type": "null"
              }
            ]
          },
          "default_country": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2,
                "minLength": 2,
                "pattern": "^[A-Za-z]{2}$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Country",
            "description": "ISO 3166-1 alpha-2 country code (e.g. 'GB', 'US'). Exactly two ASCII letters, case-insensitive. Null means no tenant-level geo override."
          },
          "byop_proxy_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Byop Proxy Url",
            "description": "External proxy endpoint URL for BYOP (Bring Your Own Proxy). Format: http://user:pass@host:port. When set, SERP sessions use this proxy instead of DataImpulse. Must be an http:// or https:// URL pointing to a public address."
          },
          "byop_no_fallback": {
            "type": "boolean",
            "title": "Byop No Fallback",
            "description": "When True, blocked BYOP sessions do NOT fall back to DataImpulse. The tenant's proxy manager handles failover internally. Only meaningful when byop_proxy_url is set.",
            "default": false
          },
          "session_slot_count": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 16.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Slot Count",
            "description": "Number of dedicated SERP session pool slots to auto-provision for this tenant. Uses default_country and byop_proxy_url (if set) for the provisioned sessions' proxy geo target. Applied automatically on org provisioning and on every tenant_config write — no env var change or worker restart required. Omit/null to leave session provisioning unchanged."
          },
          "capture_ads": {
            "type": "boolean",
            "title": "Capture Ads",
            "description": "When True, this tenant's Google SERP T4 requests exempt ad-serving domains from the resource filter so ad containers populate. Marcode-only opt-in — must stay False for every other tenant to avoid extra proxy bandwidth and detection surface.",
            "default": false
          }
        },
        "type": "object",
        "title": "TenantConfig",
        "description": "Typed shape for Organization.tenant_config JSONB column.\n\nUsed to validate updates to tenant_config and to document the expected\nschema for downstream B2B features. All fields are optional — omitted\nfields mean 'use platform default'."
      },
      "TenantConfigCustomPricing": {
        "properties": {
          "per_request_microcents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Per Request Microcents"
          }
        },
        "type": "object",
        "title": "TenantConfigCustomPricing",
        "description": "Per-tenant custom pricing overrides."
      },
      "TenantConfigDeliveryConfig": {
        "properties": {
          "s3_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "S3 Bucket"
          },
          "s3_region": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "S3 Region"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          }
        },
        "type": "object",
        "title": "TenantConfigDeliveryConfig",
        "description": "Per-tenant output delivery configuration."
      },
      "TenantConfigDeliveryResponse": {
        "properties": {
          "s3_bucket": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "S3 Bucket"
          },
          "s3_region": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "S3 Region"
          }
        },
        "type": "object",
        "title": "TenantConfigDeliveryResponse",
        "description": "Safe subset of delivery config — bucket name and region only, no credentials."
      },
      "TenantConfigRateLimitOverride": {
        "properties": {
          "requests_per_minute": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requests Per Minute"
          },
          "concurrent_requests": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Concurrent Requests"
          }
        },
        "type": "object",
        "title": "TenantConfigRateLimitOverride",
        "description": "Per-tenant rate limit overrides."
      },
      "TenantConfigRateLimitResponse": {
        "properties": {
          "requests_per_minute": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Requests Per Minute"
          },
          "concurrent_requests": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Concurrent Requests"
          }
        },
        "type": "object",
        "title": "TenantConfigRateLimitResponse",
        "description": "Safe subset of rate limit override — no pricing data."
      },
      "TenantConfigReadResponse": {
        "properties": {
          "rate_limit_override": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigRateLimitResponse"
              },
              {
                "type": "null"
              }
            ]
          },
          "default_country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Country"
          },
          "delivery_config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TenantConfigDeliveryResponse"
              },
              {
                "type": "null"
              }
            ]
          },
          "mfa_required": {
            "type": "boolean",
            "title": "Mfa Required",
            "default": false
          },
          "api_key_audit_enabled": {
            "type": "boolean",
            "title": "Api Key Audit Enabled",
            "default": false
          }
        },
        "type": "object",
        "title": "TenantConfigReadResponse",
        "description": "Public read view of tenant_config for enterprise clients.\n\nCredential fields (byop_proxy_url, byop_no_fallback, webhook_url,\ncustom_pricing, sso_config) are intentionally excluded — they contain\nsensitive data managed by admins only."
      },
      "TenantConfigSSOConfig": {
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider"
          },
          "metadata_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata Url"
          }
        },
        "type": "object",
        "title": "TenantConfigSSOConfig",
        "description": "Per-tenant SSO configuration."
      },
      "TenantDeliveryConfigClientCreate": {
        "properties": {
          "delivery_type": {
            "$ref": "#/components/schemas/DeliveryType",
            "description": "Delivery method"
          },
          "credentials": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Credentials",
            "description": "Delivery credentials (encrypted at rest). s3: {access_key_id, secret_access_key}. webhook: {signing_secret} (optional). polling/batch_export: {} (no credentials required)."
          },
          "config_json": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config Json",
            "description": "Non-secret delivery configuration. s3: {prefix, format, bucket}. webhook: {endpoint, events, headers}. polling: {format, retention_hours}. batch_export: {format, schedule}."
          },
          "freshness_target_seconds": {
            "type": "integer",
            "maximum": 604800.0,
            "minimum": 60.0,
            "title": "Freshness Target Seconds",
            "description": "Maximum acceptable data age in seconds (60s–7d). Default: 86400 (24h).",
            "default": 86400
          },
          "retry_policy_json": {
            "additionalProperties": true,
            "type": "object",
            "title": "Retry Policy Json",
            "description": "Retry policy. Example: {\"max_attempts\": 3, \"backoff_seconds\": [30, 120, 600]}"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active",
            "description": "Whether this config is active",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "delivery_type",
          "credentials"
        ],
        "title": "TenantDeliveryConfigClientCreate",
        "description": "Client-facing schema to create a new tenant delivery configuration.\n\nIdentical to TenantDeliveryConfigCreate but without tenant_id in the\nrequest body — the tenant is resolved from the caller's API key context.\n\nPer-type credential validation:\n- s3: access_key_id and secret_access_key are required.\n- webhook: signing_secret is optional (signing is opt-in); empty dict allowed.\n- polling / batch_export: no credentials required; empty dict expected."
      },
      "TenantDeliveryConfigListResponse": {
        "properties": {
          "configs": {
            "items": {
              "$ref": "#/components/schemas/TenantDeliveryConfigResponse"
            },
            "type": "array",
            "title": "Configs"
          },
          "total_count": {
            "type": "integer",
            "title": "Total Count",
            "description": "Total number of matching configs in the DB (across all pages)"
          },
          "limit": {
            "type": "integer",
            "title": "Limit",
            "description": "Page size used in this request"
          },
          "offset": {
            "type": "integer",
            "title": "Offset",
            "description": "Number of records skipped"
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "True if more records exist beyond this page"
          }
        },
        "type": "object",
        "required": [
          "configs",
          "total_count",
          "limit",
          "offset",
          "has_more"
        ],
        "title": "TenantDeliveryConfigListResponse",
        "description": "List of delivery configs for a tenant."
      },
      "TenantDeliveryConfigResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "title": "Tenant Id"
          },
          "delivery_type": {
            "$ref": "#/components/schemas/DeliveryType"
          },
          "config_json": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config Json"
          },
          "freshness_target_seconds": {
            "type": "integer",
            "title": "Freshness Target Seconds"
          },
          "retry_policy_json": {
            "additionalProperties": true,
            "type": "object",
            "title": "Retry Policy Json"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "credential_hint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Credential Hint"
          }
        },
        "type": "object",
        "required": [
          "id",
          "tenant_id",
          "delivery_type",
          "config_json",
          "freshness_target_seconds",
          "retry_policy_json",
          "is_active",
          "created_at",
          "updated_at"
        ],
        "title": "TenantDeliveryConfigResponse",
        "description": "Tenant delivery configuration response — credentials excluded."
      },
      "TenantDeliveryConfigRotateCredentials": {
        "properties": {
          "credentials": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Credentials",
            "description": "New credentials to replace the existing ones"
          }
        },
        "type": "object",
        "required": [
          "credentials"
        ],
        "title": "TenantDeliveryConfigRotateCredentials",
        "description": "Replace delivery credentials without downtime.\n\nThe old credentials are decrypted, the new credentials replace them,\nand the result is re-encrypted with a fresh nonce. The config remains active."
      },
      "TenantDeliveryConfigTestResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "delivery_type": {
            "$ref": "#/components/schemas/DeliveryType"
          }
        },
        "type": "object",
        "required": [
          "success",
          "message",
          "delivery_type"
        ],
        "title": "TenantDeliveryConfigTestResponse",
        "description": "Result of a test-connection call."
      },
      "TenantDeliveryConfigUpdate": {
        "properties": {
          "config_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config Json",
            "description": "Updated non-secret delivery configuration"
          },
          "freshness_target_seconds": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 604800.0,
                "minimum": 60.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Freshness Target Seconds",
            "description": "Updated freshness target in seconds"
          },
          "retry_policy_json": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Retry Policy Json",
            "description": "Updated retry policy"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active",
            "description": "Activate or deactivate this config"
          }
        },
        "type": "object",
        "title": "TenantDeliveryConfigUpdate",
        "description": "Update non-credential fields of a tenant delivery configuration.\n\nCredentials are rotated via a separate /rotate endpoint."
      },
      "TenantDeliveryTriggerRequest": {
        "properties": {
          "batch_id": {
            "type": "string",
            "maxLength": 128,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9._\\-]+$",
            "title": "Batch Id",
            "description": "Batch identifier for this delivery run. Becomes part of the S3 key (per_batch strategy) or audit log. Restricted to alphanumerics, '.', '_', and '-' to prevent path traversal in the delivery key. Use a descriptive name such as 'test-2026-06-19' or 'marcode-pilot-001'."
          },
          "results": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "maxItems": 1000,
            "minItems": 1,
            "title": "Results",
            "description": "Result records to deliver. Each dict is one row in the output file. For S3 delivery: serialized as JSONL (one JSON object per line). Maximum 1000 results per trigger call — use production job completion hooks for larger batches."
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "results"
        ],
        "title": "TenantDeliveryTriggerRequest",
        "description": "Trigger a manual delivery run against a configured delivery method.\n\nIntended for integration testing and Marcode pilot validation only.\nNot a production delivery pathway — result count is capped at 1000."
      },
      "TenantDeliveryTriggerResponse": {
        "properties": {
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "title": "Delivered At",
            "description": "UTC timestamp of delivery completion"
          },
          "method": {
            "type": "string",
            "title": "Method",
            "description": "Delivery method used (e.g. 's3', 'webhook', 'polling')"
          },
          "bytes_written": {
            "type": "integer",
            "title": "Bytes Written",
            "description": "Bytes uploaded to the destination"
          },
          "destination": {
            "type": "string",
            "title": "Destination",
            "description": "Full delivery destination URI (e.g. s3://bucket/prefix/batch-id.jsonl). Returned untruncated because the caller owns the destination bucket — this is self-disclosure only, not a cross-tenant leak. The success log truncates this value to 100 chars for log hygiene; that truncation is a logging convention and does not affect the API contract."
          },
          "result_count": {
            "type": "integer",
            "title": "Result Count",
            "description": "Number of result records delivered"
          },
          "signature": {
            "type": "string",
            "title": "Signature",
            "description": "HMAC-SHA256 audit signature for this delivery"
          }
        },
        "type": "object",
        "required": [
          "delivered_at",
          "method",
          "bytes_written",
          "destination",
          "result_count",
          "signature"
        ],
        "title": "TenantDeliveryTriggerResponse",
        "description": "Response from a manual delivery trigger call.\n\nContains the signed DeliveryReceipt fields for auditability.\nCredentials are NEVER included."
      },
      "TicketCreateRequest": {
        "properties": {
          "subject": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Subject",
            "description": "Ticket subject line"
          },
          "body": {
            "type": "string",
            "maxLength": 10000,
            "minLength": 1,
            "title": "Body",
            "description": "Initial message body (becomes first reply)"
          },
          "category_slug": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Slug",
            "description": "Category slug for auto-assignment; omit to let auto-categorisation decide"
          },
          "priority": {
            "$ref": "#/components/schemas/TicketPriority",
            "description": "Ticket priority; defaults to medium",
            "default": "medium"
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketSource"
              },
              {
                "type": "null"
              }
            ],
            "description": "Ticket source; defaults to 'dashboard'. Pass 'contact_form' when the ticket originates from the /contact page rather than the dashboard help widget."
          },
          "ticket_metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ticket Metadata",
            "description": "Optional JSONB metadata attached to the ticket.  Keys starting with '_' and reserved system keys (suggested_reply, duplicate_check, enrichment) are rejected."
          },
          "attachments": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/AttachmentRef"
                },
                "type": "array",
                "maxItems": 10
              },
              {
                "type": "null"
              }
            ],
            "title": "Attachments",
            "description": "Pre-uploaded attachments to link to the first reply (max 10)"
          }
        },
        "type": "object",
        "required": [
          "subject",
          "body"
        ],
        "title": "TicketCreateRequest",
        "description": "Payload for creating a new support ticket.\n\nThe ``body`` field is the content of the first reply / message — it is\nstored as the initial ``TicketReply`` row, not on the ticket itself."
      },
      "TicketListFilters": {
        "properties": {
          "status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "priority": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketPriority"
              },
              {
                "type": "null"
              }
            ]
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category",
            "description": "Filter by category slug"
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketSource"
              },
              {
                "type": "null"
              }
            ]
          },
          "assigned_to": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Assigned To",
            "description": "Filter by assigned admin UUID (admin only)"
          },
          "search": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Search",
            "description": "Full-text search on subject and first-reply body"
          },
          "date_from": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date From",
            "description": "Include tickets created at or after this timestamp"
          },
          "date_to": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date To",
            "description": "Include tickets created at or before this timestamp"
          },
          "has_unread": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Has Unread",
            "description": "Filter to tickets with unread admin replies (True) or all tickets (None)"
          }
        },
        "type": "object",
        "title": "TicketListFilters",
        "description": "Query-parameter filters for the ticket list endpoint.\n\nAll filters are optional and combine with AND semantics."
      },
      "TicketListResponse": {
        "properties": {
          "tickets": {
            "items": {
              "$ref": "#/components/schemas/TicketResponse"
            },
            "type": "array",
            "title": "Tickets"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "page": {
            "type": "integer",
            "title": "Page"
          },
          "page_size": {
            "type": "integer",
            "title": "Page Size"
          },
          "pages": {
            "type": "integer",
            "title": "Pages"
          },
          "filters": {
            "$ref": "#/components/schemas/TicketListFilters",
            "description": "Echo of the filters that produced this result set"
          }
        },
        "type": "object",
        "required": [
          "tickets",
          "total",
          "page",
          "page_size",
          "pages",
          "filters"
        ],
        "title": "TicketListResponse",
        "description": "Paginated list of tickets with an active-filters summary."
      },
      "TicketMuteRequest": {
        "properties": {
          "muted": {
            "type": "boolean",
            "title": "Muted",
            "description": "True to mute this ticket (suppress email notifications), False to unmute"
          }
        },
        "type": "object",
        "required": [
          "muted"
        ],
        "title": "TicketMuteRequest",
        "description": "Payload for PATCH /api/v1/support/tickets/{id}/mute."
      },
      "TicketMuteResponse": {
        "properties": {
          "ticket_id": {
            "type": "string",
            "format": "uuid",
            "title": "Ticket Id"
          },
          "is_muted": {
            "type": "boolean",
            "title": "Is Muted"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "ticket_id",
          "is_muted",
          "message"
        ],
        "title": "TicketMuteResponse",
        "description": "Response for PATCH /api/v1/support/tickets/{id}/mute."
      },
      "TicketPriority": {
        "type": "string",
        "enum": [
          "low",
          "medium",
          "high",
          "urgent"
        ],
        "title": "TicketPriority"
      },
      "TicketResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "ticket_ref": {
            "type": "string",
            "title": "Ticket Ref",
            "description": "Human-readable reference, e.g. ALT-1234"
          },
          "ticket_number": {
            "type": "integer",
            "title": "Ticket Number"
          },
          "user_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Id"
          },
          "category_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id"
          },
          "category": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/app__schemas__support__CategoryResponse"
              },
              {
                "type": "null"
              }
            ]
          },
          "subject": {
            "type": "string",
            "title": "Subject"
          },
          "status": {
            "$ref": "#/components/schemas/TicketStatus"
          },
          "priority": {
            "$ref": "#/components/schemas/TicketPriority"
          },
          "source": {
            "$ref": "#/components/schemas/TicketSource"
          },
          "assigned_to": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Assigned To"
          },
          "assigned_admin_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Assigned Admin Name",
            "description": "Display name of the assigned admin (joined at query time)"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "ticket_metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ticket Metadata",
            "description": "Arbitrary metadata (maps to 'metadata' column)"
          },
          "auto_category_confidence": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Auto Category Confidence"
          },
          "first_response_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "First Response At"
          },
          "resolved_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resolved At"
          },
          "satisfaction_rating": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Satisfaction Rating"
          },
          "satisfaction_comment": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Satisfaction Comment"
          },
          "is_muted": {
            "type": "boolean",
            "title": "Is Muted",
            "description": "True if the ticket owner has muted email notifications for this ticket",
            "default": false
          },
          "reply_count": {
            "type": "integer",
            "title": "Reply Count",
            "description": "Number of non-deleted, non-internal replies",
            "default": 0
          },
          "attachment_count": {
            "type": "integer",
            "title": "Attachment Count",
            "description": "Total number of attachments on the ticket and its replies",
            "default": 0
          },
          "last_reply_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Reply At",
            "description": "Timestamp of the most recent reply"
          },
          "herald_ticket_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Herald Ticket Id",
            "description": "Integer ID of the corresponding herald_tickets row. NULL if Herald sync is pending or unavailable."
          },
          "has_unread": {
            "type": "boolean",
            "title": "Has Unread",
            "description": "True if the ticket has admin replies the user has not yet read. Computed from ticket_read_receipts (migration 0208).",
            "default": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "ticket_ref",
          "ticket_number",
          "subject",
          "status",
          "priority",
          "source",
          "tags",
          "created_at",
          "updated_at"
        ],
        "title": "TicketResponse",
        "description": "Full ticket representation returned from the API."
      },
      "TicketSource": {
        "type": "string",
        "enum": [
          "dashboard",
          "contact_form",
          "email",
          "discord",
          "api"
        ],
        "title": "TicketSource"
      },
      "TicketStatus": {
        "type": "string",
        "enum": [
          "open",
          "awaiting_reply",
          "in_progress",
          "resolved",
          "closed",
          "merged"
        ],
        "title": "TicketStatus"
      },
      "TicketUpdateRequest": {
        "properties": {
          "status": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "priority": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TicketPriority"
              },
              {
                "type": "null"
              }
            ]
          },
          "category_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Category Id",
            "description": "UUID of the target category; null to clear"
          },
          "assigned_to": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Assigned To",
            "description": "Admin user UUID to assign this ticket to (admin only)"
          },
          "tags": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Tags",
            "description": "Replacement tag list (admin only); null leaves tags unchanged"
          }
        },
        "type": "object",
        "title": "TicketUpdateRequest",
        "description": "Payload for updating an existing ticket.\n\nAll fields are optional — send only the fields you want to change.\nFields that are admin-only (``assigned_to``, ``tags``) must be guarded\nat the router level with an admin dependency."
      },
      "TierBreakdownItem": {
        "properties": {
          "tier": {
            "type": "string",
            "title": "Tier"
          },
          "tier_name": {
            "type": "string",
            "title": "Tier Name"
          },
          "requests": {
            "type": "integer",
            "title": "Requests",
            "default": 0
          },
          "successful": {
            "type": "integer",
            "title": "Successful",
            "default": 0
          },
          "failed": {
            "type": "integer",
            "title": "Failed",
            "default": 0
          },
          "spend_microcents": {
            "type": "integer",
            "title": "Spend Microcents",
            "default": 0
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "tier",
          "tier_name"
        ],
        "title": "TierBreakdownItem",
        "description": "Single tier in the breakdown."
      },
      "TierBreakdownResponse": {
        "properties": {
          "api_key_id": {
            "type": "string",
            "format": "uuid",
            "title": "Api Key Id"
          },
          "days": {
            "type": "integer",
            "title": "Days"
          },
          "tiers": {
            "items": {
              "$ref": "#/components/schemas/TierBreakdownItem"
            },
            "type": "array",
            "title": "Tiers"
          }
        },
        "type": "object",
        "required": [
          "api_key_id",
          "days",
          "tiers"
        ],
        "title": "TierBreakdownResponse",
        "description": "Response for per-key tier breakdown."
      },
      "TierCapInsightRow": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "last_occurrence": {
            "type": "string",
            "title": "Last Occurrence"
          },
          "playbook_min_tier": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Playbook Min Tier"
          },
          "user_max_tier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Max Tier"
          },
          "recommended_action": {
            "type": "string",
            "title": "Recommended Action"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "failure_count",
          "last_occurrence",
          "recommended_action"
        ],
        "title": "TierCapInsightRow",
        "description": "Per-domain tier_cap_user failure insight."
      },
      "TierCapInsightsResponse": {
        "properties": {
          "insights": {
            "items": {
              "$ref": "#/components/schemas/TierCapInsightRow"
            },
            "type": "array",
            "title": "Insights"
          },
          "total_tier_cap_failures": {
            "type": "integer",
            "title": "Total Tier Cap Failures"
          }
        },
        "type": "object",
        "required": [
          "insights",
          "total_tier_cap_failures"
        ],
        "title": "TierCapInsightsResponse",
        "description": "Tier cap insights response — domains where user self-limits."
      },
      "TokenRequest": {
        "properties": {
          "grant_type": {
            "type": "string",
            "title": "Grant Type",
            "description": "Must be 'authorization_code'"
          },
          "code": {
            "type": "string",
            "title": "Code",
            "description": "Authorization code from /oauth/authorize"
          },
          "client_id": {
            "type": "string",
            "title": "Client Id"
          },
          "client_secret": {
            "type": "string",
            "title": "Client Secret"
          },
          "redirect_uri": {
            "type": "string",
            "title": "Redirect Uri"
          }
        },
        "type": "object",
        "required": [
          "grant_type",
          "code",
          "client_id",
          "client_secret",
          "redirect_uri"
        ],
        "title": "TokenRequest",
        "description": "OAuth2 token exchange request."
      },
      "TokenResponse": {
        "properties": {
          "access_token": {
            "type": "string",
            "title": "Access Token"
          },
          "token_type": {
            "type": "string",
            "title": "Token Type",
            "default": "bearer"
          },
          "scope": {
            "type": "string",
            "title": "Scope",
            "default": "scrape"
          }
        },
        "type": "object",
        "required": [
          "access_token"
        ],
        "title": "TokenResponse",
        "description": "OAuth2 token response (access_token is a real API key)."
      },
      "TopConsumersResponse": {
        "properties": {
          "top_domains": {
            "items": {
              "$ref": "#/components/schemas/TopDomainItem"
            },
            "type": "array",
            "title": "Top Domains"
          },
          "top_urls": {
            "items": {
              "$ref": "#/components/schemas/TopUrlItem"
            },
            "type": "array",
            "title": "Top Urls"
          }
        },
        "type": "object",
        "required": [
          "top_domains",
          "top_urls"
        ],
        "title": "TopConsumersResponse",
        "description": "Top consumers response with domains and URLs."
      },
      "TopDomainItem": {
        "properties": {
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "request_count": {
            "type": "integer",
            "title": "Request Count"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          },
          "avg_response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Response Time Ms"
          }
        },
        "type": "object",
        "required": [
          "domain",
          "request_count",
          "total_credits"
        ],
        "title": "TopDomainItem",
        "description": "Top consuming domain."
      },
      "TopEndpointItem": {
        "properties": {
          "endpoint": {
            "type": "string",
            "title": "Endpoint"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "avg_latency_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Latency Ms"
          },
          "error_rate": {
            "type": "number",
            "title": "Error Rate"
          }
        },
        "type": "object",
        "required": [
          "endpoint",
          "requests",
          "error_rate"
        ],
        "title": "TopEndpointItem",
        "description": "Top endpoint data item."
      },
      "TopEndpointsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/TopEndpointItem"
            },
            "type": "array",
            "title": "Data"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "TopEndpointsResponse",
        "description": "Top endpoints response."
      },
      "TopUrlItem": {
        "properties": {
          "url": {
            "type": "string",
            "title": "Url"
          },
          "request_count": {
            "type": "integer",
            "title": "Request Count"
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          }
        },
        "type": "object",
        "required": [
          "url",
          "request_count",
          "total_credits"
        ],
        "title": "TopUrlItem",
        "description": "Top consuming URL."
      },
      "TransferOwnershipRequest": {
        "properties": {
          "new_owner_id": {
            "type": "string",
            "format": "uuid",
            "title": "New Owner Id"
          }
        },
        "type": "object",
        "required": [
          "new_owner_id"
        ],
        "title": "TransferOwnershipRequest",
        "description": "Transfer organization ownership request."
      },
      "TransferOwnershipResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          },
          "new_owner": {
            "$ref": "#/components/schemas/MemberUser"
          },
          "former_owner_new_role": {
            "$ref": "#/components/schemas/OrgRole"
          }
        },
        "type": "object",
        "required": [
          "message",
          "new_owner",
          "former_owner_new_role"
        ],
        "title": "TransferOwnershipResponse",
        "description": "Transfer ownership response."
      },
      "TriggerTokenResponse": {
        "properties": {
          "trigger_url": {
            "type": "string",
            "title": "Trigger Url"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "trigger_url",
          "message"
        ],
        "title": "TriggerTokenResponse",
        "description": "Response for POST /workflows/{id}/token — token management."
      },
      "UnifiedScrapeRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url"
          },
          "mode": {
            "type": "string",
            "enum": [
              "auto",
              "html",
              "js",
              "pdf",
              "ocr"
            ],
            "title": "Mode",
            "description": "Scraping mode",
            "default": "auto"
          },
          "method": {
            "type": "string",
            "enum": [
              "GET",
              "POST"
            ],
            "title": "Method",
            "description": "HTTP method to use when fetching the target URL. Default is GET (standard page scrape). Use POST for GraphQL endpoints, REST APIs, and form submissions. POST costs 1.5x the base tier price. Body and Content-Type are optional — some endpoints (e.g. webhook triggers) accept bodyless POST.",
            "default": "GET"
          },
          "body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Body",
            "description": "Request body to send with POST. Must be a UTF-8 string. Maximum 1 MB (10 MB for high-volume/enterprise tiers). For JSON payloads (GraphQL, REST) set content_type='application/json'. For GraphQL queries set content_type='application/graphql'. For HTML forms set content_type='application/x-www-form-urlencoded'. Cannot be used with method='GET'. PRIVACY: Body content is never logged or stored in job records. Only body_size_bytes is tracked for telemetry and billing."
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "application/json",
                  "application/x-www-form-urlencoded",
                  "text/plain",
                  "application/graphql"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Type",
            "description": "Content-Type header for the request body. Defaults to 'application/json' when body is provided. Supported values: 'application/json', 'application/x-www-form-urlencoded', 'text/plain', 'application/graphql'. multipart/form-data (file uploads) is not supported. Ignored when body is not set."
          },
          "source": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "playground",
                  "api"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Request source for tracking. Set automatically by dashboard playground. API clients can omit this (defaults to 'api')."
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Custom HTTP headers to include in the request to the target URL. Hop-by-hop headers (Connection, Transfer-Encoding, Host, etc.) are not allowed."
          },
          "sync": {
            "type": "boolean",
            "title": "Sync",
            "description": "Enable blocking mode: API polls internally until job completes (60-120s max), then returns 200 with result. Simpler than manual polling, but has timeout limit. Set to False for immediate 202 response with job_id for long-running scrapes (>60s) or when using webhooks/WebSockets. Both modes queue to worker - sync just polls for you.",
            "default": true
          },
          "advanced": {
            "$ref": "#/components/schemas/AdvancedOptions"
          },
          "location": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Location"
              },
              {
                "type": "null"
              }
            ],
            "description": "Geo-targeting parameters. Routes request through a proxy in the specified country and sets Accept-Language/browser locale for localized content. Example: {\"country\": \"DE\", \"language\": \"de\"}"
          },
          "cost_controls": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CostControls"
              },
              {
                "type": "null"
              }
            ]
          },
          "cache": {
            "type": "boolean",
            "title": "Cache",
            "description": "Enable caching. When True, results may be returned from cache on repeat calls where the full cache key matches: URL, scraping mode, HTTP method, request body, output options (formats, extraction config, render settings, geo-targeting), and user identity — each user's cache is isolated. For GET: standard opt-in caching. For POST: only valid when the endpoint is idempotent (e.g. GraphQL queries, read-only REST POSTs) — caching a mutating POST will cause stale responses to be returned instead of executing the mutation.",
            "default": false
          },
          "cache_ttl": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 86400.0,
                "minimum": 60.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Cache Ttl",
            "description": "Cache TTL in seconds (60-86400). Defaults to 3600 (60 min) when cache=True."
          },
          "force_refresh": {
            "type": "boolean",
            "title": "Force Refresh",
            "description": "Force fresh fetch even if cache=True. Deprecated: prefer cache=False.",
            "default": false
          },
          "include_raw_html": {
            "type": "boolean",
            "title": "Include Raw Html",
            "default": false
          },
          "timeout": {
            "type": "integer",
            "maximum": 300.0,
            "minimum": 1.0,
            "title": "Timeout",
            "default": 90
          },
          "max_response_bytes": {
            "type": "integer",
            "maximum": 52428800.0,
            "minimum": 0.0,
            "title": "Max Response Bytes",
            "description": "Soft cap on raw response body size in bytes. When the downloaded HTML exceeds this value it is truncated before extraction and content_truncated.truncation_reason is set to 'response_body_cap'. Default: 5 MB (5_242_880). Set to 0 for no limit. Maximum: 50 MB (52_428_800).",
            "default": 5242880
          },
          "formats": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "text",
                    "json",
                    "json_v2",
                    "html",
                    "markdown",
                    "rag",
                    "content",
                    "raw"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Formats",
            "description": "Output formats for content transformation. Default: ['markdown', 'json', 'html'] - optimized for LLM workflows. Markdown preserves structure (headings, tables, lists), JSON provides structured data extraction. json_v2 provides universal deterministic extraction with section tree, classified links, and structured tables. rag provides chunked markdown with token counts and metadata for vector DB ingestion. content provides clean body_markdown + structured images (with context) + classified links (content/cta/social) + word_count + content_hash for KB/AI pipelines. raw returns the response body byte-for-byte with no transformation or metadata injection."
          },
          "extraction_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Schema",
            "description": "JSON Schema for filtering extracted data. Fields are mapped from playbook/algorithmic output using aliases. Results returned in filtered_content field. See docs for playbook output schemas."
          },
          "extraction_prompt": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Prompt",
            "description": "Natural language instructions for extraction"
          },
          "extraction_provider": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "openai",
                  "anthropic",
                  "openrouter",
                  "groq"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Provider",
            "description": "LLM provider to use for extraction. Selects the matching BYOK key registered at /dashboard/settings/llm-keys. When omitted, the most recently used registered key is used automatically."
          },
          "extraction_model": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 256
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Model",
            "description": "Per-request LLM model override in provider-specific format (e.g. 'gpt-4o', 'claude-opus-4-5-20251101', 'llama3-70b-8192'). When provided, overrides the model saved in your BYOK key settings for this request only. When omitted, the model configured on your registered key is used."
          },
          "extraction_profile": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Profile",
            "description": "Pre-defined extraction profile (schema template)",
            "default": "auto"
          },
          "extraction_template": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "auto",
                  "product",
                  "article",
                  "job_posting",
                  "faq",
                  "recipe",
                  "event",
                  "ecommerce_homepage",
                  "directory_listing"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Template",
            "description": "Shorthand for extraction_profile. Selects a pre-built schema template by name. Mutually exclusive with extraction_profile."
          },
          "evidence": {
            "type": "boolean",
            "title": "Evidence",
            "description": "Include provenance/evidence for extracted fields",
            "default": false
          },
          "promote_schema_org": {
            "type": "boolean",
            "title": "Promote Schema Org",
            "description": "Use Schema.org as primary structure when available",
            "default": true
          },
          "filter_content": {
            "type": "boolean",
            "title": "Filter Content",
            "description": "Apply quality filtering to extracted content. When False (default), returns all parsed content without quality thresholds (lossless mode).",
            "default": false
          },
          "wait_for": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Wait For"
          },
          "screenshot": {
            "type": "boolean",
            "title": "Screenshot",
            "default": false
          },
          "wait_until": {
            "type": "string",
            "title": "Wait Until",
            "default": "networkidle"
          },
          "enable_scroll": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enable Scroll",
            "description": "Force enable scrolling for lazy-load images. true: Always scroll (captures dynamic images, +5-10s), false: Never scroll (faster, may miss dynamic images), null: Auto (scroll unless social media site)"
          },
          "pdf_format": {
            "type": "string",
            "pattern": "^(text|markdown)$",
            "title": "Pdf Format",
            "default": "markdown"
          },
          "ocr_language": {
            "type": "string",
            "title": "Ocr Language",
            "default": "eng"
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url",
            "description": "Webhook URL to receive job.completed/job.failed events for this request. Bypasses pre-registered webhooks. HTTPS required (except localhost in dev)."
          },
          "embeddings": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/EmbeddingsConfig"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional embeddings configuration. When enabled, scraped text content is chunked and embedded using OpenAI models. +$0.001 per page."
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "UnifiedScrapeRequest",
        "description": "Unified scrape request supporting all modes.",
        "examples": [
          {
            "description": "Scrape a page with default settings (sync mode, auto tier selection)",
            "summary": "Basic scrape",
            "value": {
              "url": "https://example.com"
            }
          },
          {
            "description": "Scrape a JavaScript-heavy page with browser rendering",
            "summary": "JS rendering",
            "value": {
              "advanced": {
                "screenshot": true
              },
              "mode": "js",
              "timeout": 120,
              "url": "https://example.com/spa"
            }
          },
          {
            "description": "Scrape and extract structured data using an LLM prompt",
            "summary": "LLM extraction",
            "value": {
              "extraction_prompt": "Extract the product name, price, and description",
              "formats": [
                "json"
              ],
              "url": "https://example.com/products/widget"
            }
          },
          {
            "description": "Submit an async scrape job and receive results via webhook",
            "summary": "Async with webhook",
            "value": {
              "sync": false,
              "url": "https://example.com/large-page",
              "webhook_url": "https://example.com/webhook"
            }
          },
          {
            "description": "Relay a POST request to a GraphQL endpoint with a JSON body",
            "summary": "GraphQL query",
            "value": {
              "body": "{\"query\": \"{users{id name}}\"}",
              "content_type": "application/json",
              "method": "POST",
              "url": "https://api.example.com/graphql"
            }
          }
        ]
      },
      "UnifiedScrapeResponse": {
        "properties": {
          "job_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Job Id",
            "description": "Job ID for this scrape request"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "final_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Final Url",
            "description": "The URL after all redirects resolved. Equals `url` when no redirect occurred or when `follow_redirects=false`. Always populated on successful scrapes."
          },
          "redirected": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirected",
            "description": "True if the scraper followed one or more redirects before reaching the final page (`final_url != url`). False when no redirect occurred. Null on error paths."
          },
          "redirect_chain": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirect Chain",
            "description": "Ordered list of redirect hops, each with `url` and `status_code`. Populated for T1–T3 (curl_cffi) tiers when redirects occur. Null when no redirects occurred or when using T4 (browser) tier."
          },
          "status_code": {
            "type": "integer",
            "title": "Status Code"
          },
          "tier_status_codes": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "integer"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier Status Codes",
            "description": "Per-tier upstream HTTP status code trail (#30210 — structural enabler for status-based block gating, ALT-51), keyed by tier string (e.g. '1', '3', '3.5', '4'). Null when no tier-attempt diagnostics were recorded for this job."
          },
          "content": {
            "title": "Content"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Title"
          },
          "published_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Published At"
          },
          "author": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "headers": {
            "additionalProperties": {
              "type": "string"
            },
            "type": "object",
            "title": "Headers"
          },
          "cached": {
            "type": "boolean",
            "title": "Cached"
          },
          "cached_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cached At",
            "description": "ISO timestamp when result was cached"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At",
            "description": "ISO timestamp when cache entry expires"
          },
          "stale_cache": {
            "type": "boolean",
            "title": "Stale Cache",
            "description": "True if this result was served from stale cache after a scrape failure",
            "default": false
          },
          "response_time_ms": {
            "type": "integer",
            "title": "Response Time Ms"
          },
          "size_bytes": {
            "type": "integer",
            "title": "Size Bytes"
          },
          "structured_content": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Structured Content"
          },
          "structured_sections": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Structured Sections"
          },
          "raw_html": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Raw Html"
          },
          "raw": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Raw",
            "description": "Response body returned byte-for-byte with no transformation (when formats includes 'raw'). For JSON API responses, contains the compact JSON string. For HTML pages, contains the full HTML."
          },
          "warning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Warning"
          },
          "domain_warning": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain Warning",
            "description": "Human-readable warning when the target domain has a low historical success rate. The scrape will still proceed, but results may be unreliable. See domain_difficulty for structured detail."
          },
          "domain_difficulty": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Domain Difficulty",
            "description": "Structured domain difficulty detail when domain_warning is set. Contains: success_rate (float 0.0–1.0), total_attempts (int), override_active (bool)."
          },
          "tier_cap_warning": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tier Cap Warning",
            "description": "Structured tier mismatch detail when the requested tier is below the domain's playbook minimum. Always contains domain_min_tier (int) and likely_outcome (str, always \"tier_cap_exceeded\"). Two mutually exclusive shapes: (1) max_tier path — also contains your_max_tier (float), emitted when max_tier is below domain_min_tier AND domain_min_tier < 4. When domain_min_tier >= 4, this shape is instead raised as an HTTPException(422) before the response body is constructed (#31251) — it never appears in this field in that case, only in the 422's detail string and the X-Tier-Warning header; (2) force_tier path — also contains your_force_tier (int), emitted when force_tier is explicitly set below domain_min_tier (always warning-only, regardless of domain_min_tier). Also surfaced as X-Tier-Warning response header (JSON-encoded) for programmatic clients."
          },
          "content_quality": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Quality"
          },
          "quality_warning": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Quality Warning",
            "description": "Present when post-hoc soft-block detection fired on a successful scrape but the response contains usable content (word_count > 100). Full rate applies — AlterLab paid proxy/compute cost and the content is usable. Always contains: code (str), reason (str), word_count (int), content_size_bytes (int). code is always 'soft_block_posthoc'. Null for the majority of scrapes where no post-hoc soft-block was detected."
          },
          "screenshot_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Screenshot Url"
          },
          "pdf_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pdf Url"
          },
          "ocr_results": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ocr Results"
          },
          "action_results": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ActionResult"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Action Results",
            "description": "Results of browser automation actions (if actions were provided). Each entry includes index, type, success status, and optional result/screenshot."
          },
          "proxy_used": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Proxy Used",
            "description": "User's proxy integration info if BYOP was used: {id, provider, name}"
          },
          "captured_cookies": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Captured Cookies",
            "description": "Cookies set by the target during this scrape (the Set-Cookie jar), returned only when a sticky_session handle is used. A subsequent /scrape call with the same sticky_session automatically replays these cookies (they are persisted server-side for the handle's TTL), so you rarely need to read them directly — they are surfaced for transparency and manual replay. Gated to the same paid plan as sticky_session. Malformed or hostile cookie values from the target (control characters, oversized values, excessive count) are sanitized out before being returned, so this may be a smaller jar than the target's raw Set-Cookie response — or None if nothing survived sanitization (#29724)."
          },
          "filtered_content": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "items": {},
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Filtered Content",
            "description": "Filtered extraction matching user's JSON Schema (if extraction_schema provided)"
          },
          "extraction_result": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Result",
            "description": "LLM-extracted structured data (parsed JSON) from extraction_prompt or extraction_schema. Also available in content.extraction for discoverability."
          },
          "embeddings": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/EmbeddingsResult"
              },
              {
                "type": "null"
              }
            ],
            "description": "Embedding vectors for scraped content (if embeddings.enabled in request)"
          },
          "billing": {
            "$ref": "#/components/schemas/BillingDetails"
          },
          "extraction_method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Method",
            "description": "Method used for JSON extraction",
            "default": "algorithmic"
          },
          "method_details": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method Details",
            "description": "Provider, model, tokens, confidence for LLM extraction"
          },
          "version": {
            "type": "string",
            "title": "Version",
            "description": "API response envelope version. Content schema version for json_v2 is in content.json_v2.version and X-AlterLab-Schema-Version header.",
            "default": "v1"
          },
          "is_gated": {
            "type": "boolean",
            "title": "Is Gated",
            "description": "True if the page requires authentication for full content. Partial metadata (OG tags, JSON-LD) is returned instead.",
            "default": false
          },
          "extraction_completeness": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Completeness",
            "description": "Score 0.0-1.0 indicating how complete the extracted content is. Auth-gated pages typically score 0.1-0.3 (metadata only)."
          },
          "extraction_note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Note",
            "description": "Human-readable note about content extraction limitations."
          },
          "note": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Note",
            "description": "Advisory note about this request. Included when repeat-request detection identifies the same URL returning identical content across multiple requests — suggests render_js or caching to improve results."
          },
          "content_hash": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Content Hash",
            "description": "16-character truncated SHA-256 of the extracted text content. Compare this value across requests to detect content changes without diffing full responses. Identical hash = no meaningful content change. Based on text content only, so minor HTML/DOM changes that don't affect visible text do not change the hash. Null when content could not be extracted."
          },
          "content_truncated": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ContentTruncationInfo"
              },
              {
                "type": "null"
              }
            ],
            "description": "Present when the page content was truncated before extraction due to size limits. Null for the majority of pages that are within size limits."
          },
          "_meta": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ResponseMeta"
              },
              {
                "type": "null"
              }
            ],
            "description": "Attribution metadata identifying AlterLab as the data provider."
          }
        },
        "type": "object",
        "required": [
          "url",
          "status_code",
          "content",
          "headers",
          "cached",
          "response_time_ms",
          "size_bytes",
          "billing"
        ],
        "title": "UnifiedScrapeResponse",
        "description": "Enhanced scrape response with billing breakdown."
      },
      "UnlinkAccountResponse": {
        "properties": {
          "message": {
            "type": "string",
            "title": "Message"
          },
          "remaining_methods": {
            "type": "integer",
            "title": "Remaining Methods"
          }
        },
        "type": "object",
        "required": [
          "message",
          "remaining_methods"
        ],
        "title": "UnlinkAccountResponse",
        "description": "Response for unlink operation."
      },
      "UnshareResourceResponse": {
        "properties": {
          "resource_type": {
            "type": "string",
            "title": "Resource Type"
          },
          "resource_id": {
            "type": "string",
            "format": "uuid",
            "title": "Resource Id"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Resource removed from workspace"
          }
        },
        "type": "object",
        "required": [
          "resource_type",
          "resource_id"
        ],
        "title": "UnshareResourceResponse",
        "description": "Returned after successfully removing a resource from an org workspace."
      },
      "UnsubscribeRequest": {
        "properties": {
          "uid": {
            "type": "string",
            "title": "Uid"
          },
          "type": {
            "type": "string",
            "title": "Type"
          },
          "token": {
            "type": "string",
            "title": "Token"
          }
        },
        "type": "object",
        "required": [
          "uid",
          "type",
          "token"
        ],
        "title": "UnsubscribeRequest"
      },
      "UnsubscribeResponse": {
        "properties": {
          "ok": {
            "type": "boolean",
            "title": "Ok"
          },
          "message": {
            "type": "string",
            "title": "Message"
          }
        },
        "type": "object",
        "required": [
          "ok",
          "message"
        ],
        "title": "UnsubscribeResponse"
      },
      "UpdateProfileRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "email": {
            "anyOf": [
              {
                "type": "string",
                "format": "email"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          }
        },
        "type": "object",
        "title": "UpdateProfileRequest",
        "description": "Update profile request."
      },
      "UploadAttachmentResponse": {
        "properties": {
          "storage_key": {
            "type": "string",
            "title": "Storage Key"
          },
          "filename": {
            "type": "string",
            "title": "Filename"
          },
          "content_type": {
            "type": "string",
            "title": "Content Type"
          },
          "size_bytes": {
            "type": "integer",
            "title": "Size Bytes"
          }
        },
        "type": "object",
        "required": [
          "storage_key",
          "filename",
          "content_type",
          "size_bytes"
        ],
        "title": "UploadAttachmentResponse",
        "description": "Response returned immediately after a successful file upload.\n\nThe file is written to disk and a ``PendingAttachmentUpload`` row is\npersisted, binding the returned storage_key to the authenticated\nuploader (#30309).  That row is what makes the key **one-time-use and\nnon-transferable**: it is claimed atomically at link time, so a\nstorage_key echoed to any other viewer cannot be used by them, and a\nsecond claim of the same key always fails.\n\nThe caller passes this key (wrapped in AttachmentRef) to the ticket- or\nreply-creation endpoint, which claims the pending upload and creates the\nTicketAttachment row with the correct ticket_id / reply_id.  The\nserver-recorded filename / content_type from the upload are authoritative\nat that point, not the client-supplied AttachmentRef values.\n\nStorage keys are valid for **24 hours** — the background orphaned-upload\nGC removes files with no TicketAttachment row after that window."
      },
      "UsageAlertSettings": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          },
          "threshold_50_enabled": {
            "type": "boolean",
            "title": "Threshold 50 Enabled",
            "default": false
          },
          "threshold_75_enabled": {
            "type": "boolean",
            "title": "Threshold 75 Enabled",
            "default": true
          },
          "threshold_90_enabled": {
            "type": "boolean",
            "title": "Threshold 90 Enabled",
            "default": true
          },
          "threshold_100_enabled": {
            "type": "boolean",
            "title": "Threshold 100 Enabled",
            "default": true
          },
          "email_enabled": {
            "type": "boolean",
            "title": "Email Enabled",
            "default": true
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          }
        },
        "type": "object",
        "title": "UsageAlertSettings",
        "description": "User preferences for usage alerts."
      },
      "UsageAlertSettingsResponse": {
        "properties": {
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "default": true
          },
          "threshold_50_enabled": {
            "type": "boolean",
            "title": "Threshold 50 Enabled",
            "default": false
          },
          "threshold_75_enabled": {
            "type": "boolean",
            "title": "Threshold 75 Enabled",
            "default": true
          },
          "threshold_90_enabled": {
            "type": "boolean",
            "title": "Threshold 90 Enabled",
            "default": true
          },
          "threshold_100_enabled": {
            "type": "boolean",
            "title": "Threshold 100 Enabled",
            "default": true
          },
          "email_enabled": {
            "type": "boolean",
            "title": "Email Enabled",
            "default": true
          },
          "webhook_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Webhook Url"
          },
          "last_50_alert_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last 50 Alert At"
          },
          "last_75_alert_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last 75 Alert At"
          },
          "last_90_alert_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last 90 Alert At"
          },
          "last_100_alert_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last 100 Alert At"
          }
        },
        "type": "object",
        "title": "UsageAlertSettingsResponse",
        "description": "Response with usage alert settings."
      },
      "UsageBreakdownItem": {
        "properties": {
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "credits": {
            "type": "integer",
            "title": "Credits"
          }
        },
        "type": "object",
        "required": [
          "requests",
          "credits"
        ],
        "title": "UsageBreakdownItem",
        "description": "Usage breakdown by type."
      },
      "UsageBreakdownResponse": {
        "properties": {
          "light": {
            "$ref": "#/components/schemas/UsageBreakdownItem"
          },
          "js": {
            "$ref": "#/components/schemas/UsageBreakdownItem"
          },
          "pdf": {
            "$ref": "#/components/schemas/UsageBreakdownItem"
          },
          "ocr": {
            "$ref": "#/components/schemas/UsageBreakdownItem"
          },
          "crawl": {
            "$ref": "#/components/schemas/UsageBreakdownItem",
            "default": {
              "requests": 0,
              "credits": 0
            }
          },
          "total_credits": {
            "type": "integer",
            "title": "Total Credits"
          }
        },
        "type": "object",
        "required": [
          "light",
          "js",
          "pdf",
          "ocr",
          "total_credits"
        ],
        "title": "UsageBreakdownResponse",
        "description": "Usage breakdown by request type."
      },
      "UsageChartDataPoint": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "credits_used": {
            "type": "integer",
            "title": "Credits Used"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "date",
          "credits_used",
          "requests"
        ],
        "title": "UsageChartDataPoint",
        "description": "Single data point for usage chart."
      },
      "UsageChartResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/UsageChartDataPoint"
            },
            "type": "array",
            "title": "Data"
          },
          "period": {
            "type": "string",
            "title": "Period",
            "default": "30d"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "UsageChartResponse",
        "description": "Usage chart data."
      },
      "UsageDataPoint": {
        "properties": {
          "date": {
            "type": "string",
            "title": "Date"
          },
          "requests": {
            "type": "integer",
            "title": "Requests"
          },
          "cached": {
            "type": "integer",
            "title": "Cached"
          },
          "credits": {
            "type": "integer",
            "title": "Credits"
          },
          "errors": {
            "type": "integer",
            "title": "Errors"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "avg_latency_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Latency Ms"
          }
        },
        "type": "object",
        "required": [
          "date",
          "requests",
          "cached",
          "credits",
          "errors",
          "success_rate"
        ],
        "title": "UsageDataPoint",
        "description": "Usage time series data point."
      },
      "UsageEstimate": {
        "properties": {
          "avg_cost_per_request": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Cost Per Request",
            "description": "Average cost per request in microcents (1,000,000 = $1.00)"
          },
          "total_cost_microcents": {
            "type": "integer",
            "title": "Total Cost Microcents",
            "description": "Total cost in microcents during the rolling window",
            "default": 0
          },
          "request_count": {
            "type": "integer",
            "title": "Request Count",
            "description": "Number of requests during the rolling window",
            "default": 0
          },
          "window_days": {
            "type": "integer",
            "title": "Window Days",
            "description": "Rolling window size in days",
            "default": 7
          },
          "has_enough_data": {
            "type": "boolean",
            "title": "Has Enough Data",
            "description": "Whether there's sufficient data for a reliable estimate",
            "default": false
          },
          "balance_microcents": {
            "type": "integer",
            "title": "Balance Microcents",
            "description": "Current account balance in microcents",
            "default": 0
          },
          "estimated_requests": {
            "type": "integer",
            "title": "Estimated Requests",
            "description": "Estimated number of requests remaining",
            "default": 0
          },
          "default_cost_per_request": {
            "type": "integer",
            "title": "Default Cost Per Request",
            "description": "Default cost per request (Tier 1) in microcents",
            "default": 200
          }
        },
        "type": "object",
        "title": "UsageEstimate",
        "description": "Usage estimate data for the Requests Estimator feature.\n\nProvides average cost per request from a rolling window to help users\nestimate how many requests they can make with their current balance."
      },
      "UsageRealtimeResponse": {
        "properties": {
          "credits_used_today": {
            "type": "integer",
            "title": "Credits Used Today"
          },
          "credits_used_week": {
            "type": "integer",
            "title": "Credits Used Week"
          },
          "credits_used_month": {
            "type": "integer",
            "title": "Credits Used Month"
          },
          "requests_today": {
            "type": "integer",
            "title": "Requests Today"
          },
          "requests_week": {
            "type": "integer",
            "title": "Requests Week"
          },
          "requests_month": {
            "type": "integer",
            "title": "Requests Month"
          },
          "credits_remaining": {
            "type": "integer",
            "title": "Credits Remaining"
          },
          "credits_allocated": {
            "type": "integer",
            "title": "Credits Allocated"
          },
          "overage_projected": {
            "type": "integer",
            "title": "Overage Projected",
            "default": 0
          },
          "cost_projected": {
            "type": "number",
            "title": "Cost Projected"
          },
          "next_billing_date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Billing Date"
          },
          "plan_name": {
            "type": "string",
            "title": "Plan Name",
            "default": "payg"
          },
          "avg_daily_usage": {
            "type": "number",
            "title": "Avg Daily Usage",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "credits_used_today",
          "credits_used_week",
          "credits_used_month",
          "requests_today",
          "requests_week",
          "requests_month",
          "credits_remaining",
          "credits_allocated",
          "cost_projected"
        ],
        "title": "UsageRealtimeResponse",
        "description": "Real-time usage statistics for dashboard.\n\nAlterLab uses balance-based (PAYG) billing.  Several fields are kept\nfor backwards compatibility with the frontend but carry static or\nre-interpreted values:\n\n- ``credits_remaining`` — current balance in microcents\n- ``credits_allocated`` — total deposited (not a monthly cap)\n- ``overage_projected`` — DEPRECATED, always 0 (no overage in PAYG)\n- ``next_billing_date`` — DEPRECATED, always None (no billing cycle)\n- ``plan_name`` — always ``\"payg\"`` (no subscription plans)\n- ``cost_projected`` — estimated monthly spend in dollars based on\n  average daily usage"
      },
      "UsageStats": {
        "properties": {
          "credits_available": {
            "type": "integer",
            "title": "Credits Available"
          },
          "credits_used_month": {
            "type": "integer",
            "title": "Credits Used Month"
          },
          "credits_limit": {
            "type": "integer",
            "title": "Credits Limit"
          },
          "plan": {
            "type": "string",
            "title": "Plan"
          },
          "period_start": {
            "type": "string",
            "format": "date-time",
            "title": "Period Start"
          },
          "period_end": {
            "type": "string",
            "format": "date-time",
            "title": "Period End"
          }
        },
        "type": "object",
        "required": [
          "credits_available",
          "credits_used_month",
          "credits_limit",
          "plan",
          "period_start",
          "period_end"
        ],
        "title": "UsageStats",
        "description": "Usage statistics."
      },
      "UsageTimeseriesResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/UsageDataPoint"
            },
            "type": "array",
            "title": "Data"
          },
          "period_start": {
            "type": "string",
            "title": "Period Start"
          },
          "period_end": {
            "type": "string",
            "title": "Period End"
          },
          "total_days": {
            "type": "integer",
            "title": "Total Days"
          }
        },
        "type": "object",
        "required": [
          "data",
          "period_start",
          "period_end",
          "total_days"
        ],
        "title": "UsageTimeseriesResponse",
        "description": "Usage timeseries response."
      },
      "UseTemplateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "Custom name for the new workflow (defaults to template name)"
          },
          "config_overrides": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config Overrides",
            "description": "Values for template config fields (key → value)"
          }
        },
        "type": "object",
        "title": "UseTemplateRequest",
        "description": "POST /workflows/templates/{id}/use body."
      },
      "UseTemplateResponse": {
        "properties": {
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Workflow created from template."
          }
        },
        "type": "object",
        "required": [
          "workflow_id",
          "name"
        ],
        "title": "UseTemplateResponse",
        "description": "Response after creating a workflow from a template."
      },
      "UserLLMKeyCreate": {
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "openai",
              "anthropic",
              "openrouter",
              "groq"
            ],
            "title": "Provider",
            "description": "LLM provider for this key."
          },
          "raw_key": {
            "type": "string",
            "maxLength": 8192,
            "minLength": 1,
            "title": "Raw Key",
            "description": "The plaintext LLM API key. Encrypted at rest immediately on receipt. Never stored or returned in plaintext."
          },
          "key_alias": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Alias",
            "description": "Optional user-friendly label (e.g. \"My OpenAI Production Key\")."
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Model Override",
            "description": "Optional model ID in provider-specific format (e.g. \"gpt-4o\", \"openai/gpt-4o-mini\"). When omitted, the extraction router uses the provider default."
          }
        },
        "type": "object",
        "required": [
          "provider",
          "raw_key"
        ],
        "title": "UserLLMKeyCreate",
        "description": "Request body for registering a new BYOK LLM API key.\n\nThe raw key is accepted here, encrypted server-side, and NEVER returned."
      },
      "UserLLMKeyResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "provider": {
            "type": "string",
            "enum": [
              "openai",
              "anthropic",
              "openrouter",
              "groq"
            ],
            "title": "Provider"
          },
          "key_alias": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Alias"
          },
          "key_hint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Hint",
            "description": "Last 4 chars of the key prefixed with \"...\" (e.g. \"...abcd\")."
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model Override"
          },
          "is_oauth": {
            "type": "boolean",
            "title": "Is Oauth",
            "default": false
          },
          "is_valid": {
            "type": "boolean",
            "title": "Is Valid"
          },
          "last_validated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Validated At"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "provider",
          "is_valid",
          "created_at",
          "updated_at"
        ],
        "title": "UserLLMKeyResponse",
        "description": "API response for a BYOK LLM key.\n\nThe ``encrypted_key`` field is intentionally absent — raw credentials\nare never exposed in responses. Use ``key_hint`` for display."
      },
      "UserLLMKeyUpdate": {
        "properties": {
          "raw_key": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 8192,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Raw Key",
            "description": "New plaintext LLM API key to replace the existing one. Encrypted at rest on receipt."
          },
          "key_alias": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Key Alias",
            "description": "New user-friendly label."
          },
          "model_override": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 200
              },
              {
                "type": "null"
              }
            ],
            "title": "Model Override",
            "description": "New model override in provider-specific format. Pass an empty string to clear an existing override."
          }
        },
        "type": "object",
        "title": "UserLLMKeyUpdate",
        "description": "Request body for updating an existing BYOK LLM key.\n\nAt least one field must be provided. Omitted fields are left unchanged."
      },
      "UserResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "avatar_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avatar Url"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "subscription_tier": {
            "type": "string",
            "title": "Subscription Tier",
            "default": "free"
          },
          "credits_remaining": {
            "type": "integer",
            "title": "Credits Remaining",
            "default": 0
          },
          "credits_total": {
            "type": "integer",
            "title": "Credits Total",
            "default": 100
          },
          "welcome_shown": {
            "type": "boolean",
            "title": "Welcome Shown",
            "default": false
          },
          "reduced_bonus": {
            "type": "boolean",
            "title": "Reduced Bonus",
            "default": false
          },
          "tier_info": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/app__schemas__auth__TierInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "extraction": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExtractionStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "beta_features": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Beta Features",
            "default": []
          },
          "org_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Org Id"
          },
          "account_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Account Type"
          }
        },
        "type": "object",
        "required": [
          "id",
          "email",
          "created_at"
        ],
        "title": "UserResponse",
        "description": "User response."
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          },
          "input": {
            "title": "Input"
          },
          "ctx": {
            "type": "object",
            "title": "Context"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      },
      "ValidationStatus": {
        "type": "string",
        "enum": [
          "pending",
          "valid",
          "invalid",
          "error"
        ],
        "title": "ValidationStatus",
        "description": "Credential validation status."
      },
      "VerificationChallengeRequest": {
        "properties": {
          "action": {
            "type": "string",
            "title": "Action"
          },
          "method": {
            "type": "string",
            "title": "Method",
            "default": "email"
          }
        },
        "type": "object",
        "required": [
          "action"
        ],
        "title": "VerificationChallengeRequest",
        "description": "Request to initiate 2FA verification."
      },
      "VerificationChallengeResponse": {
        "properties": {
          "challenge_id": {
            "type": "string",
            "title": "Challenge Id"
          },
          "method": {
            "type": "string",
            "title": "Method"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "expires_at": {
            "type": "string",
            "title": "Expires At"
          },
          "masked_destination": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Masked Destination"
          }
        },
        "type": "object",
        "required": [
          "challenge_id",
          "method",
          "action",
          "expires_at",
          "masked_destination"
        ],
        "title": "VerificationChallengeResponse",
        "description": "2FA verification challenge response."
      },
      "VideoResultResponse": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Video title"
          },
          "url": {
            "type": "string",
            "title": "Url",
            "description": "Video URL"
          },
          "source": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source",
            "description": "Video platform (e.g. 'YouTube')"
          },
          "duration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration",
            "description": "Duration string"
          },
          "thumbnail_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Thumbnail Url",
            "description": "Thumbnail image URL"
          },
          "date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Date",
            "description": "Upload/publish date"
          }
        },
        "type": "object",
        "required": [
          "title",
          "url"
        ],
        "title": "VideoResultResponse",
        "description": "A video result (usually from YouTube) shown in the video carousel."
      },
      "WaitAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "wait",
            "title": "Type",
            "default": "wait"
          },
          "milliseconds": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 30000.0,
                "minimum": 100.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Milliseconds",
            "description": "Time to wait in ms (100-30000)"
          },
          "selector": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500
              },
              {
                "type": "null"
              }
            ],
            "title": "Selector",
            "description": "CSS selector to wait for visibility"
          }
        },
        "type": "object",
        "title": "WaitAction",
        "description": "Wait for a fixed duration or until an element is visible."
      },
      "WaitForAction": {
        "properties": {
          "type": {
            "type": "string",
            "const": "wait_for",
            "title": "Type",
            "default": "wait_for"
          },
          "selector": {
            "type": "string",
            "maxLength": 500,
            "title": "Selector",
            "description": "CSS selector to wait for"
          },
          "timeout": {
            "type": "integer",
            "maximum": 30000.0,
            "minimum": 1000.0,
            "title": "Timeout",
            "description": "Timeout in ms (default 10s)",
            "default": 10000
          }
        },
        "type": "object",
        "required": [
          "selector"
        ],
        "title": "WaitForAction",
        "description": "Wait for a specific element to appear in the DOM (fails on timeout)."
      },
      "WebhookCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Name",
            "description": "Friendly name for the webhook",
            "default": "My Webhook"
          },
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "HTTPS endpoint to receive webhook events"
          },
          "events": {
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            },
            "type": "array",
            "minItems": 1,
            "title": "Events",
            "description": "Event types to subscribe to",
            "default": [
              "job.completed"
            ]
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "WebhookCreate",
        "description": "Create a new webhook endpoint."
      },
      "WebhookDeliveryAttempt": {
        "properties": {
          "attempt": {
            "type": "integer",
            "title": "Attempt"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status Code"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "timestamp": {
            "type": "string",
            "title": "Timestamp"
          }
        },
        "type": "object",
        "required": [
          "attempt",
          "timestamp"
        ],
        "title": "WebhookDeliveryAttempt",
        "description": "A single webhook delivery attempt."
      },
      "WebhookDeliveryListResponse": {
        "properties": {
          "deliveries": {
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryResponse"
            },
            "type": "array",
            "title": "Deliveries"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "deliveries",
          "total"
        ],
        "title": "WebhookDeliveryListResponse",
        "description": "List of webhook deliveries."
      },
      "WebhookDeliveryLog": {
        "properties": {
          "batch_id": {
            "type": "string",
            "title": "Batch Id"
          },
          "webhook_url": {
            "type": "string",
            "title": "Webhook Url"
          },
          "webhook_status": {
            "type": "string",
            "title": "Webhook Status"
          },
          "attempts": {
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryAttempt"
            },
            "type": "array",
            "title": "Attempts",
            "default": []
          },
          "next_retry_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Retry At"
          }
        },
        "type": "object",
        "required": [
          "batch_id",
          "webhook_url",
          "webhook_status"
        ],
        "title": "WebhookDeliveryLog",
        "description": "Full webhook delivery log for a batch."
      },
      "WebhookDeliveryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "webhook_id": {
            "type": "string",
            "format": "uuid",
            "title": "Webhook Id"
          },
          "event_type": {
            "type": "string",
            "title": "Event Type"
          },
          "status": {
            "$ref": "#/components/schemas/WebhookDeliveryStatus"
          },
          "attempt_count": {
            "type": "integer",
            "title": "Attempt Count"
          },
          "max_attempts": {
            "type": "integer",
            "title": "Max Attempts"
          },
          "response_status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Response Status Code"
          },
          "response_time_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Response Time Ms"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "title": "Scheduled At"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "next_retry_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Retry At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "webhook_id",
          "event_type",
          "status",
          "attempt_count",
          "max_attempts",
          "scheduled_at",
          "created_at"
        ],
        "title": "WebhookDeliveryResponse",
        "description": "Webhook delivery record."
      },
      "WebhookDeliveryStatus": {
        "type": "string",
        "enum": [
          "pending",
          "success",
          "failed",
          "retrying"
        ],
        "title": "WebhookDeliveryStatus",
        "description": "Webhook delivery status."
      },
      "WebhookDetailResponse": {
        "properties": {
          "webhook": {
            "$ref": "#/components/schemas/WebhookResponse"
          },
          "recent_deliveries": {
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryResponse"
            },
            "type": "array",
            "title": "Recent Deliveries"
          },
          "stats": {
            "additionalProperties": true,
            "type": "object",
            "title": "Stats"
          }
        },
        "type": "object",
        "required": [
          "webhook",
          "recent_deliveries",
          "stats"
        ],
        "title": "WebhookDetailResponse",
        "description": "Detailed webhook info with recent deliveries."
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "job.completed",
          "job.failed",
          "job.rejected",
          "scrape.completed",
          "credits.low",
          "credits.exhausted",
          "batch.completed",
          "monitor.changed",
          "monitor.checked"
        ],
        "title": "WebhookEventType",
        "description": "Supported webhook event types."
      },
      "WebhookListResponse": {
        "properties": {
          "webhooks": {
            "items": {
              "$ref": "#/components/schemas/WebhookResponse"
            },
            "type": "array",
            "title": "Webhooks"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "webhooks",
          "total"
        ],
        "title": "WebhookListResponse",
        "description": "List of webhooks."
      },
      "WebhookResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "url": {
            "type": "string",
            "title": "Url"
          },
          "events": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Events"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "failure_count": {
            "type": "integer",
            "title": "Failure Count"
          },
          "last_failure_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Failure At"
          },
          "last_success_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Success At"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Secret"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "url",
          "events",
          "is_active",
          "failure_count",
          "created_at",
          "updated_at"
        ],
        "title": "WebhookResponse",
        "description": "Webhook endpoint details."
      },
      "WebhookStreamCredentials": {
        "properties": {
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Secret",
            "description": "HMAC-SHA256 secret for signing webhook payloads"
          }
        },
        "type": "object",
        "title": "WebhookStreamCredentials",
        "description": "Webhook streaming credentials."
      },
      "WebhookStreamOutputConfig": {
        "properties": {
          "type": {
            "type": "string",
            "const": "webhook_stream",
            "title": "Type"
          },
          "url": {
            "type": "string",
            "maxLength": 2083,
            "minLength": 1,
            "format": "uri",
            "title": "Url",
            "description": "Webhook endpoint URL to POST results to"
          },
          "headers": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Headers",
            "description": "Additional headers to include in webhook POST requests"
          },
          "credentials": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WebhookStreamCredentials"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional HMAC signing secret"
          }
        },
        "type": "object",
        "required": [
          "type",
          "url"
        ],
        "title": "WebhookStreamOutputConfig",
        "description": "Webhook stream output connector configuration."
      },
      "WebhookTestRequest": {
        "properties": {
          "event_type": {
            "$ref": "#/components/schemas/WebhookEventType",
            "description": "Event type for the test payload",
            "default": "job.completed"
          }
        },
        "type": "object",
        "title": "WebhookTestRequest",
        "description": "Request to send a test webhook event."
      },
      "WebhookTestResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "status_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status Code"
          },
          "response_time_ms": {
            "type": "integer",
            "title": "Response Time Ms"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          }
        },
        "type": "object",
        "required": [
          "success",
          "response_time_ms"
        ],
        "title": "WebhookTestResponse",
        "description": "Response from webhook test."
      },
      "WebhookUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2083,
                "minLength": 1,
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          },
          "events": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/WebhookEventType"
                },
                "type": "array",
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Events"
          },
          "is_active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Active"
          }
        },
        "type": "object",
        "title": "WebhookUpdate",
        "description": "Update an existing webhook."
      },
      "WelcomeStatusResponse": {
        "properties": {
          "reduced": {
            "type": "boolean",
            "title": "Reduced",
            "default": false
          },
          "full_bonus": {
            "type": "integer",
            "title": "Full Bonus",
            "default": 0
          },
          "received": {
            "type": "integer",
            "title": "Received",
            "default": 0
          },
          "remaining": {
            "type": "integer",
            "title": "Remaining",
            "default": 0
          },
          "sibling_accounts": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Sibling Accounts",
            "default": []
          },
          "can_unlock": {
            "type": "boolean",
            "title": "Can Unlock",
            "default": false
          },
          "has_paid": {
            "type": "boolean",
            "title": "Has Paid",
            "default": false
          },
          "unlock_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Unlock Reason"
          }
        },
        "type": "object",
        "title": "WelcomeStatusResponse",
        "description": "Welcome bonus status for reduced-bonus users."
      },
      "WorkflowAnalyticsResponse": {
        "properties": {
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count",
            "description": "Total runs in the window"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate",
            "description": "Fraction of completed runs (0.0–1.0). 0.0 when run_count is 0."
          },
          "avg_duration_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Avg Duration Ms",
            "description": "Mean duration in milliseconds across completed runs."
          },
          "p50_duration_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "P50 Duration Ms",
            "description": "Median duration in milliseconds."
          },
          "p95_duration_ms": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "P95 Duration Ms",
            "description": "95th-percentile duration in milliseconds."
          },
          "total_cost": {
            "type": "number",
            "title": "Total Cost",
            "description": "Total credits consumed in the window."
          },
          "avg_cost_per_run": {
            "type": "number",
            "title": "Avg Cost Per Run",
            "description": "Mean credits per run. 0.0 when run_count is 0."
          },
          "daily_runs": {
            "items": {
              "$ref": "#/components/schemas/DailyRunBucket"
            },
            "type": "array",
            "title": "Daily Runs",
            "description": "Per-day run counts for the window (oldest first)."
          },
          "cost_by_node_type": {
            "additionalProperties": {
              "type": "number"
            },
            "type": "object",
            "title": "Cost By Node Type",
            "description": "Total credits consumed per node type across all runs in the window. Derived from node_states.credits_used + graph_snapshot node types."
          },
          "node_success_rate": {
            "additionalProperties": {
              "type": "number"
            },
            "type": "object",
            "title": "Node Success Rate",
            "description": "Per-node-type success rate (0.0–1.0). Fraction of runs where nodes of that type completed successfully."
          },
          "days": {
            "type": "integer",
            "title": "Days",
            "description": "Number of days the window covers."
          },
          "window_start": {
            "type": "string",
            "title": "Window Start",
            "description": "ISO datetime for the start of the window."
          },
          "window_end": {
            "type": "string",
            "title": "Window End",
            "description": "ISO datetime for the end of the window."
          }
        },
        "type": "object",
        "required": [
          "workflow_id",
          "run_count",
          "success_rate",
          "total_cost",
          "avg_cost_per_run",
          "days",
          "window_start",
          "window_end"
        ],
        "title": "WorkflowAnalyticsResponse",
        "description": "GET /workflows/{id}/analytics response.\n\nAggregates execution history for a single workflow over the requested\ntime window (default: last 30 days)."
      },
      "WorkflowCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "graph": {
            "$ref": "#/components/schemas/WorkflowGraph"
          },
          "settings": {
            "additionalProperties": true,
            "type": "object",
            "title": "Settings"
          },
          "cron_expression": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron Expression"
          },
          "timezone": {
            "type": "string",
            "maxLength": 50,
            "title": "Timezone",
            "default": "UTC"
          },
          "is_reusable": {
            "type": "boolean",
            "title": "Is Reusable",
            "description": "When true, this workflow can be referenced as a sub_workflow node by other workflows belonging to the same user.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "name"
        ],
        "title": "WorkflowCreate",
        "description": "POST /workflows body."
      },
      "WorkflowEdge": {
        "properties": {
          "from": {
            "type": "string",
            "minLength": 1,
            "title": "From",
            "description": "Source node id"
          },
          "to": {
            "type": "string",
            "minLength": 1,
            "title": "To",
            "description": "Target node id"
          },
          "data_key": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Data Key",
            "description": "Key name for data passed along this edge"
          }
        },
        "type": "object",
        "required": [
          "from",
          "to",
          "data_key"
        ],
        "title": "WorkflowEdge",
        "description": "A directed edge connecting two nodes."
      },
      "WorkflowEstimateResponse": {
        "properties": {
          "estimated_microcents": {
            "type": "integer",
            "title": "Estimated Microcents"
          },
          "breakdown": {
            "additionalProperties": {
              "type": "integer"
            },
            "type": "object",
            "title": "Breakdown",
            "description": "Microcents per node type"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": ""
          },
          "warnings": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Warnings",
            "description": "Non-blocking notices about node types whose cost cannot be statically estimated (e.g. connector_action nodes billed at runtime by the provider)."
          }
        },
        "type": "object",
        "required": [
          "estimated_microcents"
        ],
        "title": "WorkflowEstimateResponse",
        "description": "POST /workflows/{id}/estimate response."
      },
      "WorkflowGraph": {
        "properties": {
          "nodes": {
            "items": {
              "$ref": "#/components/schemas/WorkflowNode"
            },
            "type": "array",
            "title": "Nodes"
          },
          "edges": {
            "items": {
              "$ref": "#/components/schemas/WorkflowEdge"
            },
            "type": "array",
            "title": "Edges"
          }
        },
        "type": "object",
        "title": "WorkflowGraph",
        "description": "The complete workflow DAG."
      },
      "WorkflowListItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "node_count": {
            "type": "integer",
            "title": "Node Count",
            "default": 0
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "is_reusable": {
            "type": "boolean",
            "title": "Is Reusable",
            "default": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "status",
          "run_count",
          "last_run_at",
          "created_at"
        ],
        "title": "WorkflowListItem",
        "description": "Lightweight workflow item for list responses."
      },
      "WorkflowListResponse": {
        "properties": {
          "workflows": {
            "items": {
              "$ref": "#/components/schemas/WorkflowListItem"
            },
            "type": "array",
            "title": "Workflows"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "workflows",
          "total"
        ],
        "title": "WorkflowListResponse",
        "description": "GET /workflows response."
      },
      "WorkflowNode": {
        "properties": {
          "id": {
            "type": "string",
            "maxLength": 100,
            "minLength": 1,
            "title": "Id",
            "description": "Unique node identifier"
          },
          "type": {
            "type": "string",
            "title": "Type",
            "description": "Node type"
          },
          "config": {
            "additionalProperties": true,
            "type": "object",
            "title": "Config",
            "description": "Node-specific configuration"
          },
          "position": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NodePosition"
              },
              {
                "type": "null"
              }
            ],
            "description": "Canvas position"
          }
        },
        "type": "object",
        "required": [
          "id",
          "type"
        ],
        "title": "WorkflowNode",
        "description": "A single node in the workflow graph."
      },
      "WorkflowResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "graph": {
            "additionalProperties": true,
            "type": "object",
            "title": "Graph"
          },
          "settings": {
            "additionalProperties": true,
            "type": "object",
            "title": "Settings"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "cron_expression": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron Expression"
          },
          "timezone": {
            "type": "string",
            "title": "Timezone"
          },
          "next_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Run At"
          },
          "run_count": {
            "type": "integer",
            "title": "Run Count"
          },
          "last_run_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Run At"
          },
          "is_reusable": {
            "type": "boolean",
            "title": "Is Reusable",
            "default": false
          },
          "trigger_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trigger Url"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "description",
          "graph",
          "settings",
          "status",
          "cron_expression",
          "timezone",
          "next_run_at",
          "run_count",
          "last_run_at",
          "created_at",
          "updated_at"
        ],
        "title": "WorkflowResponse",
        "description": "Single workflow response."
      },
      "WorkflowRetryRequest": {
        "properties": {
          "from_node": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Node",
            "description": "Node ID to retry from. Completed nodes before this are preserved."
          }
        },
        "type": "object",
        "title": "WorkflowRetryRequest",
        "description": "POST /workflows/runs/{run_id}/retry body."
      },
      "WorkflowRunListResponse": {
        "properties": {
          "runs": {
            "items": {
              "$ref": "#/components/schemas/WorkflowRunResponse"
            },
            "type": "array",
            "title": "Runs"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          }
        },
        "type": "object",
        "required": [
          "runs",
          "total"
        ],
        "title": "WorkflowRunListResponse",
        "description": "GET /workflows/{id}/runs response."
      },
      "WorkflowRunRequest": {
        "properties": {
          "input_data": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Input Data"
          }
        },
        "type": "object",
        "title": "WorkflowRunRequest",
        "description": "POST /workflows/{id}/run request body (optional)."
      },
      "WorkflowRunResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "node_states": {
            "additionalProperties": true,
            "type": "object",
            "title": "Node States"
          },
          "total_credits_used": {
            "type": "string",
            "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$",
            "title": "Total Credits Used"
          },
          "triggered_by": {
            "type": "string",
            "title": "Triggered By"
          },
          "started_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Started At"
          },
          "completed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Completed At"
          },
          "resume_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resume At"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "workflow_id",
          "status",
          "node_states",
          "total_credits_used",
          "triggered_by",
          "started_at",
          "completed_at",
          "error",
          "created_at"
        ],
        "title": "WorkflowRunResponse",
        "description": "Single run response."
      },
      "WorkflowRunTriggerResponse": {
        "properties": {
          "run_id": {
            "type": "string",
            "format": "uuid",
            "title": "Run Id"
          },
          "workflow_id": {
            "type": "string",
            "format": "uuid",
            "title": "Workflow Id"
          },
          "status": {
            "type": "string",
            "title": "Status",
            "default": "pending"
          },
          "message": {
            "type": "string",
            "title": "Message",
            "default": "Workflow execution started."
          }
        },
        "type": "object",
        "required": [
          "run_id",
          "workflow_id"
        ],
        "title": "WorkflowRunTriggerResponse",
        "description": "POST /workflows/{id}/run response."
      },
      "WorkflowTemplateListItem": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "author_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits"
          },
          "use_count": {
            "type": "integer",
            "title": "Use Count"
          },
          "is_featured": {
            "type": "boolean",
            "title": "Is Featured"
          },
          "node_count": {
            "type": "integer",
            "title": "Node Count",
            "default": 0
          },
          "price_cents": {
            "type": "integer",
            "title": "Price Cents",
            "default": 0
          },
          "is_paid": {
            "type": "boolean",
            "title": "Is Paid",
            "default": false
          },
          "fork_count": {
            "type": "integer",
            "title": "Fork Count",
            "default": 0
          },
          "review_count": {
            "type": "integer",
            "title": "Review Count",
            "default": 0
          },
          "avg_rating": {
            "type": "number",
            "title": "Avg Rating",
            "default": 0.0
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "category",
          "tags",
          "estimated_credits",
          "use_count",
          "is_featured"
        ],
        "title": "WorkflowTemplateListItem",
        "description": "Lightweight template item for gallery listing."
      },
      "WorkflowTemplateListResponse": {
        "properties": {
          "templates": {
            "items": {
              "$ref": "#/components/schemas/WorkflowTemplateListItem"
            },
            "type": "array",
            "title": "Templates"
          },
          "total": {
            "type": "integer",
            "title": "Total"
          },
          "categories": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Categories"
          }
        },
        "type": "object",
        "required": [
          "templates",
          "total"
        ],
        "title": "WorkflowTemplateListResponse",
        "description": "GET /workflows/templates response."
      },
      "WorkflowTemplateResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "author_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Author Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "category": {
            "type": "string",
            "title": "Category"
          },
          "tags": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Tags"
          },
          "graph": {
            "additionalProperties": true,
            "type": "object",
            "title": "Graph"
          },
          "config_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Config Schema"
          },
          "estimated_credits": {
            "type": "integer",
            "title": "Estimated Credits"
          },
          "use_count": {
            "type": "integer",
            "title": "Use Count"
          },
          "is_featured": {
            "type": "boolean",
            "title": "Is Featured"
          },
          "price_cents": {
            "type": "integer",
            "title": "Price Cents",
            "default": 0
          },
          "is_paid": {
            "type": "boolean",
            "title": "Is Paid",
            "default": false
          },
          "publish_status": {
            "type": "string",
            "title": "Publish Status",
            "default": "approved"
          },
          "fork_count": {
            "type": "integer",
            "title": "Fork Count",
            "default": 0
          },
          "review_count": {
            "type": "integer",
            "title": "Review Count",
            "default": 0
          },
          "avg_rating": {
            "type": "number",
            "title": "Avg Rating",
            "default": 0.0
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "description",
          "category",
          "tags",
          "graph",
          "config_schema",
          "estimated_credits",
          "use_count",
          "is_featured",
          "created_at",
          "updated_at"
        ],
        "title": "WorkflowTemplateResponse",
        "description": "Single template response."
      },
      "WorkflowUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2000
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "graph": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WorkflowGraph"
              },
              {
                "type": "null"
              }
            ]
          },
          "settings": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Settings"
          },
          "status": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "draft",
                  "active",
                  "paused",
                  "archived"
                ]
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "cron_expression": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "title": "Cron Expression"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 50
              },
              {
                "type": "null"
              }
            ],
            "title": "Timezone"
          },
          "is_reusable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Is Reusable",
            "description": "Mark or unmark this workflow as reusable by sub_workflow nodes."
          }
        },
        "type": "object",
        "title": "WorkflowUpdate",
        "description": "PATCH /workflows/{id} body."
      },
      "WorkflowValidateResponse": {
        "properties": {
          "valid": {
            "type": "boolean",
            "title": "Valid"
          },
          "errors": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Errors"
          },
          "node_count": {
            "type": "integer",
            "title": "Node Count",
            "default": 0
          },
          "edge_count": {
            "type": "integer",
            "title": "Edge Count",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "valid"
        ],
        "title": "WorkflowValidateResponse",
        "description": "POST /workflows/{id}/validate response."
      },
      "app__routers__auth__VerifyCodeRequest": {
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email"
          },
          "code": {
            "type": "string",
            "title": "Code"
          }
        },
        "type": "object",
        "required": [
          "email",
          "code"
        ],
        "title": "VerifyCodeRequest"
      },
      "app__routers__auth__VerifyCodeResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "credits_awarded": {
            "type": "integer",
            "title": "Credits Awarded"
          },
          "session_token": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Session Token"
          }
        },
        "type": "object",
        "required": [
          "success",
          "message",
          "credits_awarded"
        ],
        "title": "VerifyCodeResponse"
      },
      "app__routers__auth_extended__SessionResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "title": "Expires At"
          },
          "is_current": {
            "type": "boolean",
            "title": "Is Current"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          },
          "device_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Device Type"
          },
          "browser": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Browser"
          },
          "os": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Os"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "last_active_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Active At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "created_at",
          "expires_at",
          "is_current"
        ],
        "title": "SessionResponse",
        "description": "Session response with full device tracking."
      },
      "app__schemas__auth__TierInfo": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "requests_per_minute": {
            "type": "integer",
            "title": "Requests Per Minute"
          },
          "concurrent_requests": {
            "type": "integer",
            "title": "Concurrent Requests"
          },
          "min_balance_usd": {
            "type": "number",
            "title": "Min Balance Usd"
          },
          "max_balance_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Balance Usd"
          },
          "next_tier_slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Tier Slug"
          },
          "next_tier_threshold_usd": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Tier Threshold Usd"
          }
        },
        "type": "object",
        "required": [
          "name",
          "slug",
          "requests_per_minute",
          "concurrent_requests",
          "min_balance_usd",
          "max_balance_usd",
          "next_tier_slug",
          "next_tier_threshold_usd"
        ],
        "title": "TierInfo",
        "description": "Structured tier information derived from account balance.\n\nReturned as part of UserResponse to give API consumers a single place\nto read their current rate-limit tier without making a separate usage call."
      },
      "app__schemas__billing__AuditLogEntry": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "resource_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Type"
          },
          "resource_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Id"
          },
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error Message"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "created_at": {
            "type": "string",
            "title": "Created At"
          },
          "details": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Details"
          }
        },
        "type": "object",
        "required": [
          "id",
          "action",
          "resource_type",
          "resource_id",
          "success",
          "error_message",
          "ip_address",
          "created_at"
        ],
        "title": "AuditLogEntry",
        "description": "Audit log entry for billing operations."
      },
      "app__schemas__billing__TierInfo": {
        "properties": {
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "requests_per_minute": {
            "type": "integer",
            "title": "Requests Per Minute"
          },
          "concurrent_requests": {
            "type": "integer",
            "title": "Concurrent Requests"
          },
          "floor_cents": {
            "type": "integer",
            "title": "Floor Cents"
          },
          "next_tier": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NextTierInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "at_risk": {
            "type": "boolean",
            "title": "At Risk",
            "default": false
          },
          "at_risk_threshold": {
            "type": "number",
            "title": "At Risk Threshold",
            "default": 0.15
          }
        },
        "type": "object",
        "required": [
          "name",
          "slug",
          "requests_per_minute",
          "concurrent_requests",
          "floor_cents"
        ],
        "title": "TierInfo",
        "description": "Current balance tier information."
      },
      "app__schemas__billing__VerifyCodeRequest": {
        "properties": {
          "challenge_id": {
            "type": "string",
            "title": "Challenge Id"
          },
          "code": {
            "type": "string",
            "title": "Code"
          }
        },
        "type": "object",
        "required": [
          "challenge_id",
          "code"
        ],
        "title": "VerifyCodeRequest",
        "description": "Request to verify 2FA code."
      },
      "app__schemas__billing__VerifyCodeResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "title": "Success"
          },
          "message": {
            "type": "string",
            "title": "Message"
          },
          "remaining_attempts": {
            "type": "integer",
            "title": "Remaining Attempts",
            "default": 0
          }
        },
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "title": "VerifyCodeResponse",
        "description": "2FA verification result."
      },
      "app__schemas__organization__AuditLogEntry": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "action": {
            "type": "string",
            "title": "Action"
          },
          "target_type": {
            "type": "string",
            "title": "Target Type"
          },
          "target_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Target Id"
          },
          "details": {
            "additionalProperties": true,
            "type": "object",
            "title": "Details",
            "default": {}
          },
          "actor": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AuditLogActor"
              },
              {
                "type": "null"
              }
            ]
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "action",
          "target_type",
          "created_at"
        ],
        "title": "AuditLogEntry",
        "description": "Single audit log entry."
      },
      "app__schemas__session__SessionResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "domain": {
            "type": "string",
            "title": "Domain"
          },
          "cookie_names": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Cookie Names",
            "description": "Cookie names only — values are never exposed"
          },
          "header_names": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Header Names",
            "description": "Custom header names only — values are never exposed"
          },
          "encryption_mode": {
            "type": "string",
            "title": "Encryption Mode",
            "description": "'server' or 'client' (zero-knowledge)",
            "default": "server"
          },
          "status": {
            "type": "string",
            "title": "Status"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "last_validated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Validated At"
          },
          "validation_confidence": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Validation Confidence"
          },
          "consecutive_failures": {
            "type": "integer",
            "title": "Consecutive Failures",
            "default": 0
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "total_requests": {
            "type": "integer",
            "title": "Total Requests"
          },
          "successful_requests": {
            "type": "integer",
            "title": "Successful Requests"
          },
          "success_rate": {
            "type": "number",
            "title": "Success Rate"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes"
          },
          "auto_refresh_enabled": {
            "type": "boolean",
            "title": "Auto Refresh Enabled",
            "default": true
          },
          "notify_before_expiry": {
            "type": "boolean",
            "title": "Notify Before Expiry",
            "default": true
          },
          "notify_on_failure": {
            "type": "boolean",
            "title": "Notify On Failure",
            "default": true
          },
          "last_health_check_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Health Check At"
          },
          "fallback_count": {
            "type": "integer",
            "title": "Fallback Count",
            "default": 0
          },
          "expiry_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expiry Status",
            "description": "Expiry status: 'healthy' (>7d), 'warning' (1-7d), 'critical' (<24h), 'expired', or null"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Organization Id"
          },
          "shared": {
            "type": "boolean",
            "title": "Shared",
            "default": false
          },
          "shared_by": {
            "anyOf": [
              {
                "type": "string",
                "format": "uuid"
              },
              {
                "type": "null"
              }
            ],
            "title": "Shared By"
          },
          "shared_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Shared At"
          },
          "created_by_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Created By Name",
            "description": "Name of the user who created the session (for team views)"
          },
          "is_owner": {
            "type": "boolean",
            "title": "Is Owner",
            "description": "Whether the current user owns this session",
            "default": true
          },
          "profile_warnings": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Warnings",
            "description": "Warnings from profile-based cookie validation (missing required/optional cookies)"
          },
          "profile_slug": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Slug",
            "description": "Matched session profile slug (e.g. 'amazon'), if any"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "domain",
          "cookie_names",
          "status",
          "total_requests",
          "successful_requests",
          "success_rate",
          "created_at",
          "updated_at"
        ],
        "title": "SessionResponse",
        "description": "Response schema for a session integration. Cookie values are NEVER included."
      },
      "app__schemas__support__CategoryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "title": "Id"
          },
          "name": {
            "type": "string",
            "title": "Name"
          },
          "slug": {
            "type": "string",
            "title": "Slug"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "icon": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Icon"
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Color"
          },
          "sort_order": {
            "type": "integer",
            "title": "Sort Order"
          },
          "is_active": {
            "type": "boolean",
            "title": "Is Active"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "title": "Updated At"
          }
        },
        "type": "object",
        "required": [
          "id",
          "name",
          "slug",
          "sort_order",
          "is_active",
          "created_at",
          "updated_at"
        ],
        "title": "CategoryResponse",
        "description": "Full category representation returned from the API."
      }
    },
    "securitySchemes": {
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API key for authentication. Get yours from the [AlterLab Dashboard](https://alterlab.io/dashboard/api-keys). Format: `sk_live_...`"
      }
    }
  },
  "tags": [
    {
      "name": "Scraping (Unified)",
      "description": "Core scraping endpoint with intelligent tier escalation. Recommended for all new integrations."
    },
    {
      "name": "Scraping (Legacy)",
      "description": "Legacy per-tier scraping endpoints (light, JS, PDF, OCR). Use Unified endpoint for new integrations."
    },
    {
      "name": "Search",
      "description": "Web search with structured result extraction."
    },
    {
      "name": "Extraction",
      "description": "Structured data extraction from web pages using LLM-powered schemas."
    },
    {
      "name": "Batch",
      "description": "Submit and manage bulk scraping jobs."
    },
    {
      "name": "B2B Intake",
      "description": "Enterprise bulk intake endpoints — requires enterprise account type (account_type == 'enterprise'). Contact support to enable."
    },
    {
      "name": "Jobs",
      "description": "Poll for job status and retrieve results for delegated (async) scrapes."
    },
    {
      "name": "Schedules",
      "description": "Create recurring scrape schedules with cron expressions."
    },
    {
      "name": "Crawl",
      "description": "Discover and scrape entire websites. Start a crawl, poll for progress, cancel with automatic credit refunds. Supports depth crawling, URL filtering, priority scoring, cost controls, change tracking, output connectors, and webhooks."
    },
    {
      "name": "Crawl Schedules",
      "description": "Create recurring crawl schedules with cron expressions."
    },
    {
      "name": "Map",
      "description": "Lightweight site structure discovery without scraping. Discover URLs via sitemap parsing and link extraction. List history, compare snapshots, and export results as CSV, JSON, or Sitemap XML. Costs 1 credit per call."
    },
    {
      "name": "Map Schedules",
      "description": "Create recurring map schedules with cron expressions."
    },
    {
      "name": "Monitors",
      "description": "Configure uptime and content-change monitors for URLs."
    },
    {
      "name": "Alerts",
      "description": "Manage alert rules and notification channels for monitors."
    },
    {
      "name": "Webhooks",
      "description": "Register webhook endpoints for event-driven notifications."
    },
    {
      "name": "User Webhooks",
      "description": "User-configured webhook subscriptions for scrape and crawl events."
    },
    {
      "name": "Auth",
      "description": "Authentication, registration, and session management."
    },
    {
      "name": "Auth Extended",
      "description": "Extended authentication flows including password reset and email verification."
    },
    {
      "name": "Account Linking",
      "description": "Link and unlink external OAuth providers to an existing account."
    },
    {
      "name": "OAuth2",
      "description": "OAuth2 provider callbacks and token exchange."
    },
    {
      "name": "API Keys",
      "description": "Create, list, and revoke API keys."
    },
    {
      "name": "Organizations",
      "description": "Team and organization management with role-based access."
    },
    {
      "name": "Billing",
      "description": "Subscription management, invoices, and payment methods."
    },
    {
      "name": "Usage",
      "description": "Balance, usage history, and consumption analytics."
    },
    {
      "name": "Spend Limits",
      "description": "Configure spending limits and budget alerts."
    },
    {
      "name": "Promo Codes",
      "description": "Redeem promotional codes for bonus balance."
    },
    {
      "name": "Dashboard",
      "description": "Dashboard widgets: recent activity, usage summaries, and quick stats."
    },
    {
      "name": "Notifications",
      "description": "In-app notification feed and read-state management."
    },
    {
      "name": "Feedback",
      "description": "Submit user feedback for Cortex extraction quality improvement."
    },
    {
      "name": "Proxy Integrations",
      "description": "Bring-your-own-proxy configuration and proxy provider integrations."
    },
    {
      "name": "Session Integrations (BYOS)",
      "description": "Bring-your-own-session management for persistent browser contexts."
    },
    {
      "name": "Session Privacy (GDPR)",
      "description": "GDPR-compliant session data export and deletion."
    },
    {
      "name": "Storage Integrations",
      "description": "Connect external storage providers (S3, GCS) for scrape output delivery."
    },
    {
      "name": "Extension Reports",
      "description": "Submit and query reports from the AlterLab browser extension."
    },
    {
      "name": "Blog",
      "description": "Public blog post listing and retrieval."
    },
    {
      "name": "Announcement",
      "description": "Public product announcements and changelogs."
    },
    {
      "name": "Analytics",
      "description": "Public-facing analytics and usage statistics."
    },
    {
      "name": "Email Unsubscribe",
      "description": "One-click email unsubscribe endpoints."
    },
    {
      "name": "Favicon",
      "description": "Favicon proxy for displaying site icons in the dashboard."
    },
    {
      "name": "Firecrawl Compatible",
      "description": "Drop-in compatible endpoints for migrating from Firecrawl. Same request format, same response shape — just change the base URL."
    },
    {
      "name": "WebSocket",
      "description": "Real-time WebSocket connections for streaming scrape results."
    },
    {
      "name": "Health",
      "description": "Service health checks and readiness probes."
    },
    {
      "name": "Contexts",
      "description": "JSON-LD context document hosting for structured data."
    },
    {
      "name": "Admin Overview",
      "description": "Platform-wide admin dashboard: user counts, revenue, system status."
    }
  ],
  "security": [
    {
      "ApiKeyHeader": []
    }
  ]
}
