{
  "components": {
    "headers": {
      "CatalogAllowOrigin": {
        "description": "`*`: any website may read the catalog.",
        "required": true,
        "schema": {
          "const": "*",
          "type": "string"
        }
      },
      "CatalogCacheControl": {
        "description": "`public, max-age=300`: the catalog may be cached for 5 minutes.",
        "required": true,
        "schema": {
          "const": "public, max-age=300",
          "type": "string"
        }
      },
      "CatalogETag": {
        "description": "Strong entity tag of the catalog; changes whenever the content changes.",
        "required": true,
        "schema": {
          "pattern": "^\"[0-9a-f]{32}\"$",
          "type": "string"
        }
      },
      "Idempotent-Replayed": {
        "description": "`true` when this response replays an earlier request with the same `Idempotency-Key`.",
        "schema": {
          "const": "true",
          "type": "string"
        }
      },
      "Location": {
        "description": "`/v1/tasks/{id}`.",
        "schema": {
          "pattern": "^/v1/tasks/[0-9]+$",
          "type": "string"
        }
      },
      "Noptcha-Request-Id": {
        "description": "ID of this request (`req_…`); include it when contacting support.",
        "required": true,
        "schema": {
          "pattern": "^req_[a-z2-7]+$",
          "type": "string"
        }
      },
      "Preference-Applied": {
        "description": "`wait=N` when `Prefer: wait` or `?wait` was honoured; N is the effective wait in seconds. Absent when\nthe wait was asked for but not done because too many requests were already waiting (the response is\nthen `202` at once).\n",
        "schema": {
          "pattern": "^wait=[0-9]+$",
          "type": "string"
        }
      },
      "RateLimit": {
        "description": "`\"<name>\";r=<remaining>;t=<seconds until full>`, for example `\"create\";r=153;t=1`.",
        "schema": {
          "pattern": "^\"[a-z_]+\";r=[0-9]+;t=[0-9]+$",
          "type": "string"
        }
      },
      "RateLimit-Policy": {
        "description": "The rate limit policy, in the structured form of draft-ietf-httpapi-ratelimit-headers (not final yet):\n`\"<name>\";q=<quota>;w=<window seconds>`, for example `\"create\";q=200;w=1`. Policies: `create`\n(`POST /v1/tasks`, every response), `poll` (`GET /v1/tasks/{id}`, only when over the limit), `usage`\n(`GET /v1/usage`), `catalog` (`GET /v1/catalog`, only when over the limit; `q=600` when an IPv6 /48 is over\nits limit).\n",
        "schema": {
          "pattern": "^\"[a-z_]+\";q=[0-9]+;w=[0-9]+$",
          "type": "string"
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying.",
        "required": true,
        "schema": {
          "minimum": 1,
          "type": "integer"
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "description": "1–64 visible ASCII characters (`!` to `~`, no spaces), unique per logical request; kept for 24 hours.\nAnything else is `400 invalid_request`.\n",
        "in": "header",
        "name": "Idempotency-Key",
        "schema": {
          "examples": [
            "3f6c2b9e-8d41-4a7f-b0c5-1e2d3a4b5c6d"
          ],
          "pattern": "^[!-~]{1,64}$",
          "type": "string"
        }
      },
      "Prefer": {
        "description": "`wait=N`: wait up to N seconds (capped at 90) for the result, RFC 7240.",
        "in": "header",
        "name": "Prefer",
        "schema": {
          "examples": [
            "wait=60"
          ],
          "type": "string"
        }
      },
      "TaskId": {
        "description": "Task ID (decimal digits; the same number as the compatibility API's `taskId`).",
        "in": "path",
        "name": "id",
        "required": true,
        "schema": {
          "examples": [
            "7259140378796032"
          ],
          "pattern": "^[0-9]{1,16}$",
          "type": "string"
        }
      },
      "Wait": {
        "description": "Seconds to wait for the result (capped at 90). Takes precedence over `Prefer: wait`. Values that are\nnot a non-negative integer are ignored.\n",
        "in": "query",
        "name": "wait",
        "schema": {
          "minimum": 0,
          "type": "integer"
        }
      },
      "WebhookId": {
        "description": "Message ID, the same for every retry and manual resend of the message. Use it to deduplicate.",
        "in": "header",
        "name": "webhook-id",
        "required": true,
        "schema": {
          "examples": [
            "msg_t7259140378796032"
          ],
          "type": "string"
        }
      },
      "WebhookSignature": {
        "description": "`v1,<base64 HMAC-SHA256 of \"<webhook-id>.<webhook-timestamp>.<raw body>\">` with the secret's decoded 32 bytes.\nSeveral space-separated signatures during a rotation (the newest first); accept the request if any matches.\n",
        "in": "header",
        "name": "webhook-signature",
        "required": true,
        "schema": {
          "examples": [
            "v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4="
          ],
          "type": "string"
        }
      },
      "WebhookTimestamp": {
        "description": "Unix seconds when this attempt was sent (part of the signed content).",
        "in": "header",
        "name": "webhook-timestamp",
        "required": true,
        "schema": {
          "pattern": "^[0-9]+$",
          "type": "string"
        }
      }
    },
    "requestBodies": {
      "CompatTaskRequest": {
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CompatTaskRequest"
            }
          }
        },
        "required": true
      }
    },
    "responses": {
      "BadRequest": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`invalid_request`: the body is not valid JSON or misses a field, a parameter is wrong, `callback_url`\nis not a string, the result would be too large (usage). `unsupported_type`: the task type\ndoes not exist or is not available.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "CompatReport": {
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/CompatReportResult"
                },
                {
                  "$ref": "#/components/schemas/CompatError"
                }
              ]
            }
          }
        },
        "description": "Recorded (`errorId` 0) or an error.",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          }
        }
      },
      "Conflict": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`idempotency_conflict`: the `Idempotency-Key` was used with a different body, or the first request with\nit is still being processed (retry shortly). `task_not_solved`: feedback for a task that is not solved\n(still processing, or failed).\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "ContentTooLarge": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`request_too_large`: the body exceeds the limit (1 MB for image types, 64 KB otherwise). Any request\nwith a body over 1 MB gets this, GET requests included.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "EdgeForbidden": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`forbidden` (problem details): the request reached the API without passing through our edge network.\nInfrastructure, not part of the compatibility protocol.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          }
        }
      },
      "Forbidden": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`forbidden`: the key lacks the scope this endpoint needs, the client IP is not in the key's allowlist,\nthe key may not use this task type, or the organization is suspended (`detail` says which).\nAlso returned, without `detail`, when the request did not pass through our edge network.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "InternalError": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`internal`: an error on our side.",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "NotFound": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`not_found`: no such task, it expired (results are kept 10 minutes after completion) or it belongs to\nanother organization; or the task created with this `Idempotency-Key` has expired.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "PaymentRequired": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`insufficient_balance` or `budget_exceeded` (the key's spending budget for the period is used up).",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "ServiceUnavailable": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`service_unavailable`: no capacity right now (all solvers busy or failing, the gateway is overloaded,\na dependency is unavailable). For `POST /v1/tasks` nothing was created or charged. Wait `Retry-After`.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        }
      },
      "TooManyRequests": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`rate_limited`: too many tasks created per second by this key, the same task polled too often, the\nsandbox's per-organization rate, usage queried too often, the catalog fetched too often from this IP, or\nthis IP sent too many invalid keys.\n`concurrency_limited`: the organization has too many tasks in flight for this captcha family (or, with a\ntest key, too many sandbox tasks still processing). Wait `Retry-After` seconds.\n",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          },
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        }
      },
      "Unauthorized": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        },
        "description": "`unauthorized`: the key is malformed, unknown, revoked or expired.",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      },
      "UnprocessableContent": {
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationProblem"
            }
          }
        },
        "description": "`invalid_params`: `params` or `metadata` do not match the schema; `errors` lists each problem.",
        "headers": {
          "Noptcha-Request-Id": {
            "$ref": "#/components/headers/Noptcha-Request-Id"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimit-Policy"
          }
        }
      }
    },
    "schemas": {
      "Amount": {
        "description": "Decimal US dollars with 6 places.",
        "examples": [
          "1.230000"
        ],
        "pattern": "^-?[0-9]+\\.[0-9]{6}$",
        "type": "string"
      },
      "Balance": {
        "properties": {
          "available": {
            "$ref": "#/components/schemas/Amount",
            "description": "What new tasks can use: cash + promo + credit limit − held."
          },
          "cash": {
            "$ref": "#/components/schemas/Amount"
          },
          "credit_limit": {
            "$ref": "#/components/schemas/Amount"
          },
          "currency": {
            "const": "USD",
            "type": "string"
          },
          "held": {
            "$ref": "#/components/schemas/Amount",
            "description": "Reserved for tasks in flight."
          },
          "promo": {
            "$ref": "#/components/schemas/Amount",
            "description": "Promotional credit."
          }
        },
        "required": [
          "available",
          "cash",
          "promo",
          "held",
          "credit_limit",
          "currency"
        ],
        "type": "object"
      },
      "CallbackUrl": {
        "description": "Where to POST the task's final result (a `task.solved` or `task.failed` event, see Webhooks). `http` or\n`https`, port 80, 443, 8080 or 8443, no user info or fragment, public hosts only. `null` or `\"\"`: no callback.\n",
        "example": "https://example.com/hooks/noptcha?token=abc",
        "maxLength": 2048,
        "type": [
          "string",
          "null"
        ]
      },
      "Catalog": {
        "properties": {
          "currency": {
            "const": "USD",
            "type": "string"
          },
          "data": {
            "description": "Every public task type with a list price, ordered by `type`.",
            "items": {
              "$ref": "#/components/schemas/TypeInfo"
            },
            "type": "array"
          },
          "placeholder": {
            "description": "`true` when the prices are placeholders, not real prices (test deployments only).",
            "type": "boolean"
          },
          "price_version": {
            "description": "Version of the price list the prices come from.",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "price_version",
          "currency",
          "placeholder"
        ],
        "type": "object"
      },
      "CloudflareChallengeParams": {
        "additionalProperties": false,
        "properties": {
          "block_image": {
            "description": "Do not load images of the target page (saves proxy traffic).",
            "type": "boolean"
          },
          "post_data": {
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "If set, submitted to website_url as an HTML form POST.",
            "maxProperties": 64,
            "type": "object"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "required_cookies": {
            "description": "Cookie names that must all be obtained for the task to succeed, e.g. [\"cf_clearance\"].",
            "items": {
              "maxLength": 256,
              "minLength": 1,
              "type": "string"
            },
            "maxItems": 32,
            "type": "array",
            "uniqueItems": true
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "Usually omit it. The User-Agent actually used is returned in the solution."
          },
          "wait_load": {
            "description": "Wait for the page's network activity to settle before returning.",
            "type": "boolean"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "proxy"
        ],
        "title": "Cloudflare challenge page parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "CloudflareChallengeSolution": {
        "additionalProperties": false,
        "properties": {
          "content": {
            "description": "HTML of the target page after passing the challenge.",
            "type": "string"
          },
          "cookies": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Cookies after passing the challenge, name to value; usually includes cf_clearance.",
            "type": "object"
          },
          "headers": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Response headers of the target page.",
            "type": "object"
          },
          "request_headers": {
            "additionalProperties": {
              "type": "string"
            },
            "description": "Request headers of the browser's last request to the target page.",
            "type": "object"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the cookies are bound to; use it for every follow-up request."
          }
        },
        "required": [
          "cookies",
          "user_agent"
        ],
        "title": "Cloudflare challenge page solution",
        "type": "object",
        "x-schema-version": 1
      },
      "CompatBalance": {
        "properties": {
          "balance": {
            "description": "Available balance in US dollars.",
            "type": "number"
          },
          "errorId": {
            "const": 0,
            "type": "integer"
          }
        },
        "required": [
          "errorId",
          "balance"
        ],
        "type": "object"
      },
      "CompatCallback": {
        "description": "The compatibility API's callback body: the `getTaskResult` response for the final result, plus `taskId`.\nCallbacks for sandbox tasks (created with a test key) also carry `\"sandbox\": true`; treat such a\ncallback as a test, never as a real result.\n",
        "oneOf": [
          {
            "properties": {
              "cost": {
                "pattern": "^[0-9]+\\.[0-9]{6}$",
                "type": "string"
              },
              "createTime": {
                "type": "integer"
              },
              "endTime": {
                "type": "integer"
              },
              "errorId": {
                "const": 0,
                "type": "integer"
              },
              "ip": {
                "type": "string"
              },
              "sandbox": {
                "const": true,
                "description": "Present (true) only for sandbox tasks.",
                "type": "boolean"
              },
              "solution": {
                "$ref": "#/components/schemas/CompatSolution"
              },
              "solveCount": {
                "minimum": 1,
                "type": "integer"
              },
              "status": {
                "const": "ready",
                "type": "string"
              },
              "taskId": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "errorId",
              "status",
              "solution",
              "cost",
              "ip",
              "createTime",
              "endTime",
              "solveCount",
              "taskId"
            ],
            "type": "object"
          },
          {
            "properties": {
              "errorCode": {
                "examples": [
                  "ERROR_CAPTCHA_UNSOLVABLE"
                ],
                "type": "string"
              },
              "errorDescription": {
                "type": "string"
              },
              "errorId": {
                "const": 1,
                "type": "integer"
              },
              "sandbox": {
                "const": true,
                "description": "Present (true) only for sandbox tasks.",
                "type": "boolean"
              },
              "taskId": {
                "format": "int64",
                "type": "integer"
              }
            },
            "required": [
              "errorId",
              "errorCode",
              "errorDescription",
              "taskId"
            ],
            "type": "object"
          }
        ]
      },
      "CompatCreateTaskRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CompatKeyRequest"
          },
          {
            "properties": {
              "appId": {
                "description": "Same as `softId`.",
                "type": [
                  "integer",
                  "string"
                ]
              },
              "callbackUrl": {
                "description": "Where to POST the final result (the `getTaskResult` response plus `taskId`, see the `compatCallback`\nwebhook). Same rules as v1 `callback_url`; an invalid URL is `ERROR_INCORRECT_SESSION_DATA`. Empty: no callback.\n",
                "maxLength": 2048,
                "type": "string"
              },
              "softId": {
                "description": "Developer programme ID (digits); recorded with the task.",
                "type": [
                  "integer",
                  "string"
                ]
              },
              "task": {
                "$ref": "#/components/schemas/CompatTask"
              }
            },
            "required": [
              "task"
            ],
            "type": "object"
          }
        ]
      },
      "CompatCreateTaskResult": {
        "dependentRequired": {
          "status": [
            "solution",
            "cost"
          ]
        },
        "properties": {
          "cost": {
            "description": "Only when solved synchronously.",
            "pattern": "^[0-9]+\\.[0-9]{6}$",
            "type": "string"
          },
          "errorId": {
            "const": 0,
            "type": "integer"
          },
          "solution": {
            "$ref": "#/components/schemas/CompatSolution"
          },
          "status": {
            "const": "ready",
            "description": "Only when solved synchronously.",
            "type": "string"
          },
          "taskId": {
            "description": "Task ID (53-bit integer, safe in JavaScript).",
            "format": "int64",
            "type": "integer"
          }
        },
        "required": [
          "errorId",
          "taskId"
        ],
        "type": "object"
      },
      "CompatError": {
        "description": "A request or task error. `errorCode` values (anti-captcha's codes; new ones may be added):\n\n| errorCode | when |\n| --- | --- |\n| `ERROR_KEY_DOES_NOT_EXIST` | key malformed, unknown, revoked or expired; or the key lacks the scope this endpoint needs |\n| `ERROR_ZERO_BALANCE` | balance too low, or the key's budget is used up |\n| `ERROR_IP_NOT_ALLOWED` | client IP not in the key's allowlist |\n| `ERROR_IP_BLOCKED` | too many invalid keys from this IP |\n| `ERROR_ACCOUNT_SUSPENDED` | the organization is suspended |\n| `ERROR_NO_SLOT_AVAILABLE` | no capacity, concurrency limit, create rate limit (also sandbox limits), temporary or internal error; retry later |\n| `ERROR_TASK_NOT_SUPPORTED` | unknown task type name, or type not allowed for the key |\n| `ERROR_TASK_ABSENT` | `task` missing or not an object (or the body could not be read) |\n| `ERROR_NO_SUCH_CAPCHA_ID` | `taskId` missing, unknown, expired or of another organization; report for an unsolved task |\n| `ERROR_INCORRECT_SESSION_DATA` | a parameter does not match the schema (`errorDescription` names it), or `callbackUrl` is not allowed |\n| `ERROR_RECAPTCHA_INVALID_SITEKEY` | the site key is invalid (parameter check or solver) |\n| `ERROR_RECAPTCHA_INVALID_DOMAIN` | the website URL, API domain or subdomain is invalid or not allowed |\n| `ERROR_ZERO_CAPTCHA_FILESIZE` | the image is missing or empty |\n| `ERROR_TOO_BIG_CAPTCHA_FILESIZE` | the image (characters or pixels) or the request body is too large |\n| `ERROR_IMAGE_TYPE_NOT_SUPPORTED` | the image is not valid base64, not a PNG, JPEG, GIF, WebP or BMP image, or malformed or truncated (checked when the task is created); or the solver could not read it (task failed) |\n| `ERROR_CAPTCHA_UNSOLVABLE` | the task failed: unsolvable, timed out, or no solver accepts these parameters |\n| `ERROR_PROXY_CONNECT_REFUSED`, `ERROR_PROXY_CONNECT_TIMEOUT`, `ERROR_PROXY_READ_TIMEOUT`, `ERROR_PROXY_BANNED`, `ERROR_PROXY_TRANSPARENT`, `ERROR_PROXY_HAS_NO_IMAGE_SUPPORT`, `ERROR_PROXY_INCOMPATIBLE_HTTP_VERSION` | the proxy could not be used (task failed) |\n| `ERROR_TOKEN_EXPIRED` | the solver reported the token expired (task failed) |\n",
        "properties": {
          "errorCode": {
            "examples": [
              "ERROR_ZERO_BALANCE"
            ],
            "type": "string"
          },
          "errorDescription": {
            "type": "string"
          },
          "errorId": {
            "const": 1,
            "type": "integer"
          }
        },
        "required": [
          "errorId",
          "errorCode",
          "errorDescription"
        ],
        "type": "object",
        "x-noptcha-codes": [
          "ERROR_KEY_DOES_NOT_EXIST",
          "ERROR_ZERO_BALANCE",
          "ERROR_IP_NOT_ALLOWED",
          "ERROR_IP_BLOCKED",
          "ERROR_ACCOUNT_SUSPENDED",
          "ERROR_NO_SLOT_AVAILABLE",
          "ERROR_TASK_NOT_SUPPORTED",
          "ERROR_TASK_ABSENT",
          "ERROR_NO_SUCH_CAPCHA_ID",
          "ERROR_INCORRECT_SESSION_DATA",
          "ERROR_RECAPTCHA_INVALID_SITEKEY",
          "ERROR_RECAPTCHA_INVALID_DOMAIN",
          "ERROR_ZERO_CAPTCHA_FILESIZE",
          "ERROR_TOO_BIG_CAPTCHA_FILESIZE",
          "ERROR_IMAGE_TYPE_NOT_SUPPORTED",
          "ERROR_CAPTCHA_UNSOLVABLE",
          "ERROR_PROXY_CONNECT_REFUSED",
          "ERROR_PROXY_CONNECT_TIMEOUT",
          "ERROR_PROXY_READ_TIMEOUT",
          "ERROR_PROXY_BANNED",
          "ERROR_PROXY_TRANSPARENT",
          "ERROR_PROXY_HAS_NO_IMAGE_SUPPORT",
          "ERROR_PROXY_INCOMPATIBLE_HTTP_VERSION",
          "ERROR_TOKEN_EXPIRED"
        ]
      },
      "CompatKeyRequest": {
        "properties": {
          "clientKey": {
            "description": "Your key (`nop_live_…` or `nop_test_…`).",
            "type": "string"
          }
        },
        "required": [
          "clientKey"
        ],
        "type": "object"
      },
      "CompatReportResult": {
        "properties": {
          "errorId": {
            "const": 0,
            "type": "integer"
          },
          "status": {
            "const": "success",
            "type": "string"
          }
        },
        "required": [
          "errorId",
          "status"
        ],
        "type": "object"
      },
      "CompatSolution": {
        "additionalProperties": true,
        "description": "The answer in anti-captcha's field names for the task type name used to create the task (for example\n`gRecaptchaResponse` and `userAgent` for reCAPTCHA, `token` for Turnstile, `text` for images). The\nmapping from the canonical solution is listed per name in `CompatTaskType` (`solution`). Tasks created\nthrough v1 use the first compatible name of their type and variant.\n",
        "type": "object"
      },
      "CompatTask": {
        "additionalProperties": true,
        "description": "The task in anti-captcha's format: `type` (see `CompatTaskType`) plus that type's fields\n(`websiteURL`, `websiteKey`, `body`, …; the field map per name is in `CompatTaskType`). Unknown fields are\nignored. Parameters are validated against the canonical type's schema (see `CreateTaskRequest`).\n\nProxy names (`…Task`, without `Proxyless`) need a proxy: `proxyType` (`http`, `https`, `socks4`,\n`socks5`), `proxyAddress`, `proxyPort`, optional `proxyLogin` and `proxyPassword`; or `proxy` as a URL\nstring `http://user:pass@host:port`. Proxyless names ignore proxy fields.\n",
        "properties": {
          "proxyAddress": {
            "type": "string"
          },
          "proxyLogin": {
            "type": "string"
          },
          "proxyPassword": {
            "type": "string"
          },
          "proxyPort": {
            "type": [
              "integer",
              "string"
            ]
          },
          "proxyType": {
            "enum": [
              "http",
              "https",
              "socks4",
              "socks5"
            ],
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/CompatTaskType"
          }
        },
        "required": [
          "type"
        ],
        "type": "object"
      },
      "CompatTaskProcessing": {
        "properties": {
          "errorId": {
            "const": 0,
            "type": "integer"
          },
          "status": {
            "const": "processing",
            "type": "string"
          }
        },
        "required": [
          "errorId",
          "status"
        ],
        "type": "object"
      },
      "CompatTaskReady": {
        "properties": {
          "cost": {
            "description": "US dollars, e.g. `\"0.001000\"`.",
            "pattern": "^[0-9]+\\.[0-9]{6}$",
            "type": "string"
          },
          "createTime": {
            "description": "Unix seconds.",
            "type": "integer"
          },
          "endTime": {
            "description": "Unix seconds.",
            "type": "integer"
          },
          "errorId": {
            "const": 0,
            "type": "integer"
          },
          "ip": {
            "description": "Client IP that created the task (empty for sandbox tasks).",
            "type": "string"
          },
          "solution": {
            "$ref": "#/components/schemas/CompatSolution"
          },
          "solveCount": {
            "description": "Solver attempts.",
            "minimum": 1,
            "type": "integer"
          },
          "status": {
            "const": "ready",
            "type": "string"
          }
        },
        "required": [
          "errorId",
          "status",
          "solution",
          "cost",
          "ip",
          "createTime",
          "endTime",
          "solveCount"
        ],
        "type": "object"
      },
      "CompatTaskRequest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CompatKeyRequest"
          },
          {
            "properties": {
              "taskId": {
                "description": "The task ID, as a number or a string of digits.",
                "oneOf": [
                  {
                    "format": "int64",
                    "type": "integer"
                  },
                  {
                    "pattern": "^\\s*[0-9]+\\s*$",
                    "type": "string"
                  }
                ]
              }
            },
            "required": [
              "taskId"
            ],
            "type": "object"
          }
        ]
      },
      "CompatTaskType": {
        "description": "Task type name in the compatibility API (case-insensitive). Each name maps to a canonical type and variant (see `CreateTaskRequest` for the parameters). Names ending in `Proxyless` ignore proxy fields; the others require a proxy. Unknown names: `ERROR_TASK_NOT_SUPPORTED`.\n\n`x-noptcha-aliases` lists, per name, `fields` (compatibility field → canonical parameter; `null`: accepted but not passed on; `to_array`: a single value is wrapped in an array) and `solution` (canonical solution field → compatibility field; `index_bools`: selected indexes become one boolean per image or tile).\n\n| Name | Canonical type | Variant | Notes |\n| --- | --- | --- | --- |\n| `FunCaptchaClassification` | `image.funcaptcha` | proxyless |  |\n| `FunCaptchaTask` | `funcaptcha` | proxy |  |\n| `FunCaptchaTaskProxyless` | `funcaptcha` | proxyless |  |\n| `HCaptchaClassification` | `image.grid.hcaptcha` | proxyless |  |\n| `HCaptchaTask` | `hcaptcha` | proxy |  |\n| `HCaptchaTaskProxyless` | `hcaptcha` | proxyless |  |\n| `ImageToTextTask` | `image.text` | proxyless |  |\n| `NoCaptchaTask` | `recaptcha.v2` | proxy |  |\n| `NoCaptchaTaskProxyless` | `recaptcha.v2` | proxyless |  |\n| `ReCaptchaV2Classification` | `image.grid.recaptcha` | proxyless |  |\n| `RecaptchaV2EnterpriseTask` | `recaptcha.v2.enterprise` | proxy |  |\n| `RecaptchaV2EnterpriseTaskProxyless` | `recaptcha.v2.enterprise` | proxyless |  |\n| `RecaptchaV2Task` | `recaptcha.v2` | proxy |  |\n| `RecaptchaV2TaskProxyless` | `recaptcha.v2` | proxyless |  |\n| `RecaptchaV3EnterpriseTask` | `recaptcha.v3.enterprise` | proxyless |  |\n| `RecaptchaV3TaskProxyless` | `recaptcha.v3` | proxyless | `isEnterprise: true` → `recaptcha.v3.enterprise` |\n| `TurnstileTask` | `turnstile` | proxy |  |\n| `TurnstileTaskProxyless` | `turnstile` | proxyless |  |\n",
        "examples": [
          "FunCaptchaClassification",
          "FunCaptchaTask",
          "FunCaptchaTaskProxyless"
        ],
        "type": "string",
        "x-noptcha-aliases": [
          {
            "fields": {
              "image": {
                "conv": "to_array",
                "to": "images"
              },
              "question": "question"
            },
            "name": "FunCaptchaClassification",
            "solution": [
              {
                "from": "objects",
                "to": "objects"
              }
            ],
            "type": "image.funcaptcha",
            "variant": "proxyless"
          },
          {
            "fields": {
              "data": "data",
              "funcaptchaApiJSSubdomain": "api_subdomain",
              "userAgent": "user_agent",
              "websitePublicKey": "website_public_key",
              "websiteURL": "website_url"
            },
            "name": "FunCaptchaTask",
            "solution": [
              {
                "from": "token",
                "to": "token"
              }
            ],
            "type": "funcaptcha",
            "variant": "proxy"
          },
          {
            "fields": {
              "data": "data",
              "funcaptchaApiJSSubdomain": "api_subdomain",
              "userAgent": "user_agent",
              "websitePublicKey": "website_public_key",
              "websiteURL": "website_url"
            },
            "name": "FunCaptchaTaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "token"
              }
            ],
            "type": "funcaptcha",
            "variant": "proxyless"
          },
          {
            "fields": {
              "anchors": {
                "conv": "to_array",
                "to": "anchors"
              },
              "queries": "images",
              "question": "question"
            },
            "name": "HCaptchaClassification",
            "solution": [
              {
                "conv": "index_bools",
                "from": "objects",
                "len_param": "images",
                "to": "objects"
              },
              {
                "from": "objects",
                "to": "top_k"
              },
              {
                "from": "confidences",
                "to": "confidences"
              }
            ],
            "type": "image.grid.hcaptcha",
            "variant": "proxyless"
          },
          {
            "fields": {
              "enterprisePayload": "enterprise_payload",
              "isInvisible": "is_invisible",
              "rqdata": "enterprise_payload.rqdata",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "HCaptchaTask",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              },
              {
                "from": "resp_key",
                "to": "respKey"
              }
            ],
            "type": "hcaptcha",
            "variant": "proxy"
          },
          {
            "fields": {
              "enterprisePayload": "enterprise_payload",
              "isInvisible": "is_invisible",
              "rqdata": "enterprise_payload.rqdata",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "HCaptchaTaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              },
              {
                "from": "resp_key",
                "to": "respKey"
              }
            ],
            "type": "hcaptcha",
            "variant": "proxyless"
          },
          {
            "fields": {
              "body": "image",
              "case": "case_sensitive",
              "image": "image",
              "math": "math",
              "maxLength": "max_length",
              "minLength": "min_length",
              "numeric": "numeric",
              "phrase": "phrase"
            },
            "name": "ImageToTextTask",
            "solution": [
              {
                "from": "text",
                "to": "text"
              }
            ],
            "type": "image.text",
            "variant": "proxyless"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "NoCaptchaTask",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2",
            "variant": "proxy"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "NoCaptchaTaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2",
            "variant": "proxyless"
          },
          {
            "fields": {
              "body": "image",
              "confidence": "confidence",
              "image": "image",
              "question": "question"
            },
            "name": "ReCaptchaV2Classification",
            "solution": [
              {
                "from": "objects",
                "to": "objects"
              },
              {
                "from": "has_object",
                "to": "hasObject"
              },
              {
                "from": "confidences",
                "to": "confidences"
              }
            ],
            "type": "image.grid.recaptcha",
            "variant": "proxyless"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV2EnterpriseTask",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2.enterprise",
            "variant": "proxy"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV2EnterpriseTaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2.enterprise",
            "variant": "proxyless"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV2Task",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2",
            "variant": "proxy"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV2TaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v2",
            "variant": "proxyless"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV3EnterpriseTask",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v3.enterprise",
            "variant": "proxyless"
          },
          {
            "fields": {
              "apiDomain": "api_domain",
              "cookies": "cookies",
              "enterprisePayload": "enterprise_payload",
              "isEnterprise": null,
              "isInvisible": "is_invisible",
              "minScore": "min_score",
              "pageAction": "page_action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "RecaptchaV3TaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "gRecaptchaResponse"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "recaptcha.v3",
            "type_if": [
              {
                "equals": true,
                "field": "isEnterprise",
                "type": "recaptcha.v3.enterprise"
              }
            ],
            "variant": "proxyless"
          },
          {
            "fields": {
              "data": "cdata",
              "pageAction": "action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "TurnstileTask",
            "solution": [
              {
                "from": "token",
                "to": "token"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "turnstile",
            "variant": "proxy"
          },
          {
            "fields": {
              "data": "cdata",
              "pageAction": "action",
              "userAgent": "user_agent",
              "websiteKey": "website_key",
              "websiteURL": "website_url"
            },
            "name": "TurnstileTaskProxyless",
            "solution": [
              {
                "from": "token",
                "to": "token"
              },
              {
                "from": "user_agent",
                "to": "userAgent"
              }
            ],
            "type": "turnstile",
            "variant": "proxyless"
          }
        ]
      },
      "Confidences": {
        "items": {
          "maximum": 1,
          "minimum": 0,
          "type": "number"
        },
        "maxItems": 64,
        "type": "array"
      },
      "CreateCloudflareChallengeTaskRequest": {
        "description": "Cloudflare challenge page (`cloudflare.challenge`, family `cloudflare`, active). Variants: `proxy` (`params.proxy` is required). Tasks not solved within 120 seconds fail with `timeout`.",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/CloudflareChallengeParams"
          },
          "type": {
            "const": "cloudflare.challenge",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "Cloudflare challenge page task",
        "type": "object"
      },
      "CreateFuncaptchaTaskRequest": {
        "description": "FunCaptcha (Arkose Labs) (`funcaptcha`, family `arkose`, beta). Variants: `proxyless`, `proxy` (the `proxy` variant when `params.proxy` is given). Tasks not solved within 180 seconds fail with `timeout`.\n\nCompatibility API names: `FunCaptchaTask` (proxy), `FunCaptchaTaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/FuncaptchaParams"
          },
          "type": {
            "const": "funcaptcha",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "FunCaptcha (Arkose Labs) task",
        "type": "object"
      },
      "CreateHcaptchaTaskRequest": {
        "description": "hCaptcha (`hcaptcha`, family `hcaptcha`, active). Variants: `proxyless`, `proxy` (the `proxy` variant when `params.proxy` is given). Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `HCaptchaTask` (proxy), `HCaptchaTaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/HcaptchaParams"
          },
          "type": {
            "const": "hcaptcha",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "hCaptcha task",
        "type": "object"
      },
      "CreateImageFuncaptchaTaskRequest": {
        "description": "FunCaptcha image (`image.funcaptcha`, family `image`, beta). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.\n\nCompatibility API names: `FunCaptchaClassification` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/ImageFuncaptchaParams"
          },
          "type": {
            "const": "image.funcaptcha",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "FunCaptcha image task",
        "type": "object"
      },
      "CreateImageGridAwsTaskRequest": {
        "description": "AWS WAF image grid (`image.grid.aws`, family `image`, beta). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/ImageGridAwsParams"
          },
          "type": {
            "const": "image.grid.aws",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "AWS WAF image grid task",
        "type": "object"
      },
      "CreateImageGridHcaptchaTaskRequest": {
        "description": "hCaptcha image grid (`image.grid.hcaptcha`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.\n\nCompatibility API names: `HCaptchaClassification` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/ImageGridHcaptchaParams"
          },
          "type": {
            "const": "image.grid.hcaptcha",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "hCaptcha image grid task",
        "type": "object"
      },
      "CreateImageGridRecaptchaTaskRequest": {
        "description": "reCAPTCHA image grid (`image.grid.recaptcha`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.\n\nCompatibility API names: `ReCaptchaV2Classification` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/ImageGridRecaptchaParams"
          },
          "type": {
            "const": "image.grid.recaptcha",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "reCAPTCHA image grid task",
        "type": "object"
      },
      "CreateImageTextTaskRequest": {
        "description": "Image to text (`image.text`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.\n\nCompatibility API names: `ImageToTextTask` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/ImageTextParams"
          },
          "type": {
            "const": "image.text",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "Image to text task",
        "type": "object"
      },
      "CreateRecaptchaV2EnterpriseTaskRequest": {
        "description": "reCAPTCHA v2 Enterprise (`recaptcha.v2.enterprise`, family `recaptcha`, active). Variants: `proxyless`, `proxy` (the `proxy` variant when `params.proxy` is given). Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `RecaptchaV2EnterpriseTask` (proxy), `RecaptchaV2EnterpriseTaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/RecaptchaV2EnterpriseParams"
          },
          "type": {
            "const": "recaptcha.v2.enterprise",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "reCAPTCHA v2 Enterprise task",
        "type": "object"
      },
      "CreateRecaptchaV2TaskRequest": {
        "description": "reCAPTCHA v2 (`recaptcha.v2`, family `recaptcha`, active). Variants: `proxyless`, `proxy` (the `proxy` variant when `params.proxy` is given). Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `NoCaptchaTask` (proxy), `NoCaptchaTaskProxyless` (proxyless), `RecaptchaV2Task` (proxy), `RecaptchaV2TaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/RecaptchaV2Params"
          },
          "type": {
            "const": "recaptcha.v2",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "reCAPTCHA v2 task",
        "type": "object"
      },
      "CreateRecaptchaV3EnterpriseTaskRequest": {
        "description": "reCAPTCHA v3 Enterprise (`recaptcha.v3.enterprise`, family `recaptcha`, active). Variants: `proxyless`. Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `RecaptchaV3EnterpriseTask` (proxyless), `RecaptchaV3TaskProxyless` (proxyless, with `isEnterprise: true`).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/RecaptchaV3EnterpriseParams"
          },
          "type": {
            "const": "recaptcha.v3.enterprise",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "reCAPTCHA v3 Enterprise task",
        "type": "object"
      },
      "CreateRecaptchaV3TaskRequest": {
        "description": "reCAPTCHA v3 (`recaptcha.v3`, family `recaptcha`, active). Variants: `proxyless`. Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `RecaptchaV3TaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/RecaptchaV3Params"
          },
          "type": {
            "const": "recaptcha.v3",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "reCAPTCHA v3 task",
        "type": "object"
      },
      "CreateTaskRequest": {
        "description": "A task: `type` selects the parameters schema. New types may be added.\n\n| `type` | Name | Family | Variants | Timeout | Status |\n| --- | --- | --- | --- | --- | --- |\n| `cloudflare.challenge` | Cloudflare challenge page | `cloudflare` | `proxy` | 120 s | active |\n| `funcaptcha` | FunCaptcha (Arkose Labs) | `arkose` | `proxyless`, `proxy` | 180 s | beta |\n| `hcaptcha` | hCaptcha | `hcaptcha` | `proxyless`, `proxy` | 120 s | active |\n| `image.funcaptcha` | FunCaptcha image | `image` | `proxyless` | 60 s | beta |\n| `image.grid.aws` | AWS WAF image grid | `image` | `proxyless` | 60 s | beta |\n| `image.grid.hcaptcha` | hCaptcha image grid | `image` | `proxyless` | 60 s | active |\n| `image.grid.recaptcha` | reCAPTCHA image grid | `image` | `proxyless` | 60 s | active |\n| `image.text` | Image to text | `image` | `proxyless` | 60 s | active |\n| `recaptcha.v2` | reCAPTCHA v2 | `recaptcha` | `proxyless`, `proxy` | 120 s | active |\n| `recaptcha.v2.enterprise` | reCAPTCHA v2 Enterprise | `recaptcha` | `proxyless`, `proxy` | 120 s | active |\n| `recaptcha.v3` | reCAPTCHA v3 | `recaptcha` | `proxyless` | 120 s | active |\n| `recaptcha.v3.enterprise` | reCAPTCHA v3 Enterprise | `recaptcha` | `proxyless` | 120 s | active |\n| `turnstile` | Cloudflare Turnstile | `cloudflare` | `proxyless`, `proxy` | 120 s | active |\n",
        "discriminator": {
          "mapping": {
            "cloudflare.challenge": "#/components/schemas/CreateCloudflareChallengeTaskRequest",
            "funcaptcha": "#/components/schemas/CreateFuncaptchaTaskRequest",
            "hcaptcha": "#/components/schemas/CreateHcaptchaTaskRequest",
            "image.funcaptcha": "#/components/schemas/CreateImageFuncaptchaTaskRequest",
            "image.grid.aws": "#/components/schemas/CreateImageGridAwsTaskRequest",
            "image.grid.hcaptcha": "#/components/schemas/CreateImageGridHcaptchaTaskRequest",
            "image.grid.recaptcha": "#/components/schemas/CreateImageGridRecaptchaTaskRequest",
            "image.text": "#/components/schemas/CreateImageTextTaskRequest",
            "recaptcha.v2": "#/components/schemas/CreateRecaptchaV2TaskRequest",
            "recaptcha.v2.enterprise": "#/components/schemas/CreateRecaptchaV2EnterpriseTaskRequest",
            "recaptcha.v3": "#/components/schemas/CreateRecaptchaV3TaskRequest",
            "recaptcha.v3.enterprise": "#/components/schemas/CreateRecaptchaV3EnterpriseTaskRequest",
            "turnstile": "#/components/schemas/CreateTurnstileTaskRequest"
          },
          "propertyName": "type"
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/CreateCloudflareChallengeTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateFuncaptchaTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateHcaptchaTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateImageFuncaptchaTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateImageGridAwsTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateImageGridHcaptchaTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateImageGridRecaptchaTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateImageTextTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateRecaptchaV2TaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateRecaptchaV2EnterpriseTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateRecaptchaV3TaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateRecaptchaV3EnterpriseTaskRequest"
          },
          {
            "$ref": "#/components/schemas/CreateTurnstileTaskRequest"
          }
        ]
      },
      "CreateTurnstileTaskRequest": {
        "description": "Cloudflare Turnstile (`turnstile`, family `cloudflare`, active). Variants: `proxyless`, `proxy` (the `proxy` variant when `params.proxy` is given). Tasks not solved within 120 seconds fail with `timeout`.\n\nCompatibility API names: `TurnstileTask` (proxy), `TurnstileTaskProxyless` (proxyless).",
        "properties": {
          "callback_url": {
            "$ref": "#/components/schemas/CallbackUrl"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "$ref": "#/components/schemas/TurnstileParams"
          },
          "type": {
            "const": "turnstile",
            "type": "string"
          }
        },
        "required": [
          "type",
          "params"
        ],
        "title": "Cloudflare Turnstile task",
        "type": "object"
      },
      "EnterprisePayload": {
        "additionalProperties": true,
        "description": "Extra enterprise parameters passed to the widget as is, e.g. {\"s\": \"...\"} for reCAPTCHA Enterprise or {\"rqdata\": \"...\"} for hCaptcha.",
        "maxProperties": 32,
        "type": "object"
      },
      "FeedbackRequest": {
        "properties": {
          "correct": {
            "description": "Whether the answer was accepted by the target site.",
            "type": "boolean"
          },
          "reason": {
            "description": "Optional free text; not stored.",
            "type": "string"
          }
        },
        "required": [
          "correct"
        ],
        "type": "object"
      },
      "FeedbackResult": {
        "properties": {
          "accepted": {
            "const": true,
            "type": "boolean"
          },
          "id": {
            "pattern": "^[0-9]+$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "accepted"
        ],
        "type": "object"
      },
      "FieldError": {
        "properties": {
          "message": {
            "examples": [
              "is required"
            ],
            "type": "string"
          },
          "pointer": {
            "description": "JSON Pointer (RFC 6901) to the offending value, from the root of the request body:\n`/params/website_key`, `/params/proxy/port`, `/params` for the parameters object itself,\n`/metadata/order`, `/metadata` for the metadata object itself.\n",
            "examples": [
              "/params/website_url",
              "/metadata/order"
            ],
            "type": "string"
          },
          "reason": {
            "description": "Machine-readable kind, present for image problems: `image_too_large` (over 1,000,000 characters, the\npixel or frame limits, or the images of the task together over the per-task limit; the pointer is the\nimage that went over), `image_empty`, `image_base64` (not valid base64), `image_format` (not a PNG,\nJPEG, GIF, WebP or BMP image, a multi-picture JPEG, or malformed or truncated). New values may be added.\n",
            "enum": [
              "image_too_large",
              "image_empty",
              "image_base64",
              "image_format"
            ],
            "type": "string"
          }
        },
        "required": [
          "pointer",
          "message"
        ],
        "type": "object"
      },
      "FuncaptchaParams": {
        "additionalProperties": false,
        "properties": {
          "api_subdomain": {
            "$ref": "#/components/schemas/Hostname",
            "description": "Subdomain that serves the widget, e.g. client-api.arkoselabs.com."
          },
          "data": {
            "description": "Extra blob data as a JSON string, e.g. {\"blob\":\"...\"}.",
            "maxLength": 16384,
            "minLength": 1,
            "type": "string"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_public_key": {
            "description": "The public key (data-pkey).",
            "maxLength": 128,
            "minLength": 1,
            "type": "string"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_public_key"
        ],
        "title": "FunCaptcha (Arkose Labs) parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "FuncaptchaSolution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          }
        },
        "required": [
          "token"
        ],
        "title": "FunCaptcha (Arkose Labs) solution",
        "type": "object",
        "x-schema-version": 1
      },
      "HcaptchaParams": {
        "additionalProperties": false,
        "properties": {
          "enterprise_payload": {
            "$ref": "#/components/schemas/EnterprisePayload"
          },
          "is_invisible": {
            "description": "true for the invisible hCaptcha.",
            "type": "boolean"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "hCaptcha parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "HcaptchaSolution": {
        "additionalProperties": false,
        "properties": {
          "resp_key": {
            "description": "Value some sites require together with the token (respKey).",
            "type": "string"
          },
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "hCaptcha solution",
        "type": "object",
        "x-schema-version": 1
      },
      "Hostname": {
        "format": "hostname",
        "maxLength": 253,
        "minLength": 1,
        "type": "string"
      },
      "Image": {
        "description": "Base64-encoded PNG, JPEG, GIF, WebP or BMP image (standard or URL-safe alphabet; a data:image/...;base64, prefix, line breaks and missing padding are accepted). At most 1,000,000 characters, 8192 pixels per side and 8,388,608 pixels in total; animated images at most 1000 frames and 8,388,608 pixels for frames x width x height; multi-picture JPEG (MPO), JPEG with more than 100 scans, malformed or truncated images are rejected.",
        "maxLength": 1000000,
        "minLength": 1,
        "type": "string"
      },
      "ImageFuncaptchaParams": {
        "additionalProperties": false,
        "properties": {
          "images": {
            "description": "Base64 of each challenge image (at most 20).",
            "items": {
              "$ref": "#/components/schemas/Image"
            },
            "maxItems": 20,
            "minItems": 1,
            "type": "array"
          },
          "question": {
            "$ref": "#/components/schemas/Question",
            "description": "The question in English, e.g. Pick the image that is the correct way up."
          }
        },
        "required": [
          "images",
          "question"
        ],
        "title": "FunCaptcha image parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageFuncaptchaSolution": {
        "additionalProperties": false,
        "properties": {
          "objects": {
            "$ref": "#/components/schemas/Indexes"
          }
        },
        "required": [
          "objects"
        ],
        "title": "FunCaptcha image solution",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridAwsParams": {
        "additionalProperties": false,
        "properties": {
          "image": {
            "$ref": "#/components/schemas/Image",
            "description": "Base64 of the whole 3x3 grid image."
          },
          "question": {
            "$ref": "#/components/schemas/Question",
            "description": "The full question as shown on the page, e.g. Select all hats."
          }
        },
        "required": [
          "image"
        ],
        "title": "AWS WAF image grid parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridAwsSolution": {
        "additionalProperties": false,
        "properties": {
          "confidences": {
            "$ref": "#/components/schemas/Confidences"
          },
          "objects": {
            "$ref": "#/components/schemas/Indexes"
          }
        },
        "required": [
          "objects"
        ],
        "title": "AWS WAF image grid solution",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridHcaptchaParams": {
        "additionalProperties": false,
        "allOf": [
          {
            "anyOf": [
              {
                "properties": {
                  "question": {}
                },
                "required": [
                  "question"
                ]
              },
              {
                "properties": {
                  "anchors": {}
                },
                "required": [
                  "anchors"
                ]
              }
            ]
          }
        ],
        "properties": {
          "anchors": {
            "description": "Base64 of the example images shown next to the question.",
            "items": {
              "$ref": "#/components/schemas/Image"
            },
            "maxItems": 10,
            "minItems": 1,
            "type": "array"
          },
          "images": {
            "description": "Base64 of each challenge image in page order.",
            "items": {
              "$ref": "#/components/schemas/Image"
            },
            "maxItems": 20,
            "minItems": 1,
            "type": "array"
          },
          "question": {
            "$ref": "#/components/schemas/Question",
            "description": "The full question as shown on the page."
          }
        },
        "required": [
          "images"
        ],
        "title": "hCaptcha image grid parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridHcaptchaSolution": {
        "additionalProperties": false,
        "properties": {
          "confidences": {
            "$ref": "#/components/schemas/Confidences"
          },
          "objects": {
            "$ref": "#/components/schemas/Indexes"
          }
        },
        "required": [
          "objects"
        ],
        "title": "hCaptcha image grid solution",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridRecaptchaParams": {
        "additionalProperties": false,
        "properties": {
          "confidence": {
            "description": "3x3 only: return every tile scoring above this threshold instead of the top 3.",
            "maximum": 1,
            "minimum": 0,
            "type": "number"
          },
          "grid": {
            "description": "Grid shape. Inferred from the image size when omitted.",
            "enum": [
              "1x1",
              "3x3",
              "4x4"
            ]
          },
          "image": {
            "$ref": "#/components/schemas/Image",
            "description": "Base64 of the whole challenge image (3x3 or 4x4 grid) or of a single 1x1 tile."
          },
          "question": {
            "$ref": "#/components/schemas/Question",
            "description": "Question ID such as /m/0k4j."
          }
        },
        "required": [
          "image",
          "question"
        ],
        "title": "reCAPTCHA image grid parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageGridRecaptchaSolution": {
        "additionalProperties": false,
        "allOf": [
          {
            "anyOf": [
              {
                "properties": {
                  "objects": {}
                },
                "required": [
                  "objects"
                ]
              },
              {
                "properties": {
                  "has_object": {}
                },
                "required": [
                  "has_object"
                ]
              }
            ]
          }
        ],
        "properties": {
          "confidences": {
            "$ref": "#/components/schemas/Confidences"
          },
          "has_object": {
            "description": "1x1 tile: whether the tile contains the target.",
            "type": "boolean"
          },
          "objects": {
            "$ref": "#/components/schemas/Indexes"
          }
        },
        "required": [],
        "title": "reCAPTCHA image grid solution",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageTextParams": {
        "additionalProperties": false,
        "properties": {
          "case_sensitive": {
            "description": "The answer is case-sensitive.",
            "type": "boolean"
          },
          "image": {
            "$ref": "#/components/schemas/Image"
          },
          "math": {
            "description": "The image is an arithmetic expression; the answer is its result.",
            "type": "boolean"
          },
          "max_length": {
            "description": "Maximum answer length; 0 means no limit.",
            "maximum": 100,
            "minimum": 0,
            "type": "integer"
          },
          "min_length": {
            "description": "Minimum answer length; 0 means no limit.",
            "maximum": 100,
            "minimum": 0,
            "type": "integer"
          },
          "numeric": {
            "description": "0 no requirement; 1 digits only; 2 no digits.",
            "enum": [
              0,
              1,
              2
            ]
          },
          "phrase": {
            "description": "The answer contains at least one space.",
            "type": "boolean"
          }
        },
        "required": [
          "image"
        ],
        "title": "Image to text parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "ImageTextSolution": {
        "additionalProperties": false,
        "properties": {
          "text": {
            "description": "Recognized text.",
            "maxLength": 1024,
            "minLength": 1,
            "type": "string"
          }
        },
        "required": [
          "text"
        ],
        "title": "Image to text solution",
        "type": "object",
        "x-schema-version": 1
      },
      "Indexes": {
        "description": "Zero-based indexes of the images or tiles to select, left to right, top to bottom.",
        "items": {
          "maximum": 63,
          "minimum": 0,
          "type": "integer"
        },
        "maxItems": 64,
        "type": "array",
        "uniqueItems": true
      },
      "Me": {
        "properties": {
          "budget": {
            "description": "The key's spending budget; `null` when unlimited.",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "properties": {
                  "limit": {
                    "$ref": "#/components/schemas/Money"
                  },
                  "period": {
                    "description": "Calendar day / week from Monday / month (UTC), or a lifetime total.",
                    "enum": [
                      "day",
                      "week",
                      "month",
                      "total"
                    ],
                    "type": "string"
                  },
                  "remaining": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/Money"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "used": {
                    "description": "Spent or reserved in the current period; `null` when it cannot be read right now. Always zero for test keys.",
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/Money"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "period",
                  "limit",
                  "used",
                  "remaining"
                ],
                "type": "object"
              }
            ]
          },
          "key": {
            "properties": {
              "allow_cidrs": {
                "description": "Client IP ranges this key may be used from; `null` = any.",
                "items": {
                  "examples": [
                    "203.0.113.0/24"
                  ],
                  "type": "string"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "allowed_types": {
                "description": "Task types this key may use; `null` = all.",
                "items": {
                  "type": "string"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "expires_at": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "last4": {
                "type": "string"
              },
              "mode": {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "prefix": {
                "examples": [
                  "nop_live_AbCd"
                ],
                "type": "string"
              },
              "revoke_at": {
                "description": "When a rotated key stops working.",
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": [
                  "string",
                  "null"
                ]
              },
              "scopes": {
                "items": {
                  "examples": [
                    "tasks:write",
                    "balance:read",
                    "usage:read"
                  ],
                  "type": "string"
                },
                "type": "array"
              }
            },
            "required": [
              "id",
              "name",
              "prefix",
              "last4",
              "mode",
              "scopes",
              "allowed_types",
              "allow_cidrs",
              "expires_at",
              "revoke_at"
            ],
            "type": "object"
          },
          "limits": {
            "properties": {
              "concurrency_by_family": {
                "additionalProperties": {
                  "type": "integer"
                },
                "description": "Tasks in flight allowed for this organization, per captcha family (`recaptcha`, `hcaptcha`, …). Every public family is listed. Creating a task beyond the limit returns 429 `concurrency_limited`. Contact support to raise it.",
                "type": "object"
              },
              "concurrency_per_family": {
                "description": "Default number of tasks in flight per captcha family. Your organization may have a different limit for some families; `concurrency_by_family` has the limit that actually applies.",
                "type": "integer"
              },
              "create_tasks": {
                "description": "Tasks this key may create per window; `null` when disabled.",
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/RatePolicy"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "sandbox": {
                "description": "Present for test keys.",
                "properties": {
                  "create_tasks_per_org": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/RatePolicy"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "in_flight_per_org": {
                    "type": "integer"
                  },
                  "waits_per_org_per_process": {
                    "type": "integer"
                  }
                },
                "required": [
                  "create_tasks_per_org",
                  "in_flight_per_org",
                  "waits_per_org_per_process"
                ],
                "type": "object"
              },
              "task_polls": {
                "description": "Polls per task per window (including bursts); `null` when disabled.",
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/RatePolicy"
                  },
                  {
                    "type": "null"
                  }
                ]
              },
              "wait_max_seconds": {
                "description": "Longest synchronous wait.",
                "type": "integer"
              }
            },
            "required": [
              "create_tasks",
              "task_polls",
              "concurrency_per_family",
              "concurrency_by_family",
              "wait_max_seconds"
            ],
            "type": "object"
          },
          "organization": {
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "status": {
                "examples": [
                  "active"
                ],
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "status"
            ],
            "type": "object"
          }
        },
        "required": [
          "organization",
          "key",
          "budget",
          "limits"
        ],
        "type": "object"
      },
      "Metadata": {
        "additionalProperties": {
          "maxLength": 256,
          "type": "string"
        },
        "description": "Your own key-value pairs, returned with the task. At most 16 keys; keys 1–64 characters, values\nstrings of at most 256 characters (Unicode code points, as JSON Schema counts them). A value that is\nnot a string is `422 invalid_params` with pointer `/metadata/<key>`.\n",
        "maxProperties": 16,
        "propertyNames": {
          "maxLength": 64,
          "minLength": 1
        },
        "type": "object"
      },
      "Money": {
        "properties": {
          "amount": {
            "description": "Decimal US dollars with 6 places.",
            "examples": [
              "0.000900"
            ],
            "pattern": "^-?[0-9]+\\.[0-9]{6}$",
            "type": "string"
          },
          "currency": {
            "const": "USD",
            "type": "string"
          }
        },
        "required": [
          "amount",
          "currency"
        ],
        "type": "object"
      },
      "Problem": {
        "description": "An error, as RFC 9457 problem details (`application/problem+json`). Use `code` in programs; `type` is\n`https://noptcha.com/docs/errors/<code>`. New codes may be added.\n\n| code | HTTP | when |\n| --- | --- | --- |\n| `invalid_request` | 400 | malformed body, missing field, bad parameter, `callback_url` not a string |\n| `unsupported_type` | 400 | unknown or unavailable task type |\n| `unauthorized` | 401 | invalid, revoked or expired key |\n| `insufficient_balance` | 402 | balance too low for the task's price |\n| `budget_exceeded` | 402 | the key's budget for the period is used up |\n| `forbidden` | 403 | missing scope, IP not allowed, type not allowed, organization suspended |\n| `not_found` | 404 | unknown endpoint or method; unknown, expired or foreign task; expired idempotent task |\n| `idempotency_conflict` | 409 | same `Idempotency-Key` with another body, or still in progress |\n| `task_not_solved` | 409 | feedback for a task that is still processing or failed |\n| `request_too_large` | 413 | body over the limit |\n| `invalid_params` | 422 | `params` or `metadata` do not match the schema, or `callback_url` is not allowed |\n| `rate_limited` | 429 | over a rate limit, or IP blocked after invalid keys |\n| `concurrency_limited` | 429 | too many tasks in flight |\n| `internal` | 500 | our error |\n| `service_unavailable` | 503 | no capacity or a dependency is down |\n",
        "properties": {
          "code": {
            "description": "Machine-readable error code (see the table).",
            "type": "string"
          },
          "detail": {
            "description": "Human-readable explanation of this occurrence.",
            "type": "string"
          },
          "request_id": {
            "description": "Same as the `Noptcha-Request-Id` header.",
            "type": "string"
          },
          "status": {
            "description": "The HTTP status code.",
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "examples": [
              "https://noptcha.com/docs/errors/insufficient_balance"
            ],
            "format": "uri",
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code",
          "request_id"
        ],
        "type": "object",
        "x-noptcha-codes": [
          {
            "code": "invalid_request",
            "status": [
              400
            ]
          },
          {
            "code": "unsupported_type",
            "status": [
              400
            ]
          },
          {
            "code": "unauthorized",
            "status": [
              401
            ]
          },
          {
            "code": "insufficient_balance",
            "status": [
              402
            ]
          },
          {
            "code": "budget_exceeded",
            "status": [
              402
            ]
          },
          {
            "code": "forbidden",
            "status": [
              403
            ]
          },
          {
            "code": "not_found",
            "status": [
              404
            ]
          },
          {
            "code": "idempotency_conflict",
            "status": [
              409
            ]
          },
          {
            "code": "task_not_solved",
            "status": [
              409
            ]
          },
          {
            "code": "request_too_large",
            "status": [
              413
            ]
          },
          {
            "code": "invalid_params",
            "status": [
              422
            ]
          },
          {
            "code": "rate_limited",
            "status": [
              429
            ]
          },
          {
            "code": "concurrency_limited",
            "status": [
              429
            ]
          },
          {
            "code": "internal",
            "status": [
              500
            ]
          },
          {
            "code": "service_unavailable",
            "status": [
              503
            ]
          }
        ]
      },
      "Proxy": {
        "additionalProperties": false,
        "description": "Proxy the solver must use. login and password are used in memory only and are never stored or logged.",
        "properties": {
          "host": {
            "description": "IP address or host name. Private and loopback addresses are rejected.",
            "maxLength": 253,
            "minLength": 1,
            "type": "string"
          },
          "login": {
            "maxLength": 256,
            "type": "string"
          },
          "password": {
            "maxLength": 256,
            "type": "string"
          },
          "port": {
            "maximum": 65535,
            "minimum": 1,
            "type": "integer"
          },
          "type": {
            "enum": [
              "http",
              "https",
              "socks4",
              "socks5"
            ]
          }
        },
        "required": [
          "type",
          "host",
          "port"
        ],
        "type": "object"
      },
      "Question": {
        "maxLength": 1024,
        "minLength": 1,
        "type": "string"
      },
      "RatePolicy": {
        "properties": {
          "limit": {
            "type": "integer"
          },
          "window_seconds": {
            "type": "integer"
          }
        },
        "required": [
          "limit",
          "window_seconds"
        ],
        "type": "object"
      },
      "RecaptchaV2EnterpriseParams": {
        "additionalProperties": false,
        "properties": {
          "api_domain": {
            "$ref": "#/components/schemas/Hostname",
            "description": "Domain the widget is loaded from, e.g. www.recaptcha.net. Omit for the default."
          },
          "cookies": {
            "description": "Cookies for the target site, as in a Cookie header: name1=value1; name2=value2.",
            "maxLength": 8192,
            "type": "string"
          },
          "enterprise_payload": {
            "$ref": "#/components/schemas/EnterprisePayload"
          },
          "is_invisible": {
            "description": "true for the invisible reCAPTCHA.",
            "type": "boolean"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "reCAPTCHA v2 Enterprise parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV2EnterpriseSolution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "reCAPTCHA v2 Enterprise solution",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV2Params": {
        "additionalProperties": false,
        "properties": {
          "api_domain": {
            "$ref": "#/components/schemas/Hostname",
            "description": "Domain the widget is loaded from, e.g. www.recaptcha.net. Omit for the default."
          },
          "cookies": {
            "description": "Cookies for the target site, as in a Cookie header: name1=value1; name2=value2.",
            "maxLength": 8192,
            "type": "string"
          },
          "is_invisible": {
            "description": "true for the invisible reCAPTCHA.",
            "type": "boolean"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "reCAPTCHA v2 parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV2Solution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "reCAPTCHA v2 solution",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV3EnterpriseParams": {
        "additionalProperties": false,
        "properties": {
          "api_domain": {
            "$ref": "#/components/schemas/Hostname",
            "description": "Domain the widget is loaded from, e.g. www.recaptcha.net. Omit for the default."
          },
          "cookies": {
            "description": "Cookies for the target site, as in a Cookie header: name1=value1; name2=value2.",
            "maxLength": 8192,
            "type": "string"
          },
          "enterprise_payload": {
            "$ref": "#/components/schemas/EnterprisePayload"
          },
          "min_score": {
            "description": "Minimum score the token should reach (0.1 to 0.9).",
            "maximum": 0.9,
            "minimum": 0.1,
            "type": "number"
          },
          "page_action": {
            "description": "The action passed to grecaptcha.execute.",
            "maxLength": 256,
            "minLength": 1,
            "type": "string"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "reCAPTCHA v3 Enterprise parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV3EnterpriseSolution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "reCAPTCHA v3 Enterprise solution",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV3Params": {
        "additionalProperties": false,
        "properties": {
          "api_domain": {
            "$ref": "#/components/schemas/Hostname",
            "description": "Domain the widget is loaded from, e.g. www.recaptcha.net. Omit for the default."
          },
          "cookies": {
            "description": "Cookies for the target site, as in a Cookie header: name1=value1; name2=value2.",
            "maxLength": 8192,
            "type": "string"
          },
          "min_score": {
            "description": "Minimum score the token should reach (0.1 to 0.9).",
            "maximum": 0.9,
            "minimum": 0.1,
            "type": "number"
          },
          "page_action": {
            "description": "The action passed to grecaptcha.execute.",
            "maxLength": 256,
            "minLength": 1,
            "type": "string"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "reCAPTCHA v3 parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "RecaptchaV3Solution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "reCAPTCHA v3 solution",
        "type": "object",
        "x-schema-version": 1
      },
      "Solution": {
        "anyOf": [
          {
            "$ref": "#/components/schemas/CloudflareChallengeSolution"
          },
          {
            "$ref": "#/components/schemas/FuncaptchaSolution"
          },
          {
            "$ref": "#/components/schemas/HcaptchaSolution"
          },
          {
            "$ref": "#/components/schemas/ImageFuncaptchaSolution"
          },
          {
            "$ref": "#/components/schemas/ImageGridAwsSolution"
          },
          {
            "$ref": "#/components/schemas/ImageGridHcaptchaSolution"
          },
          {
            "$ref": "#/components/schemas/ImageGridRecaptchaSolution"
          },
          {
            "$ref": "#/components/schemas/ImageTextSolution"
          },
          {
            "$ref": "#/components/schemas/RecaptchaV2Solution"
          },
          {
            "$ref": "#/components/schemas/RecaptchaV2EnterpriseSolution"
          },
          {
            "$ref": "#/components/schemas/RecaptchaV3Solution"
          },
          {
            "$ref": "#/components/schemas/RecaptchaV3EnterpriseSolution"
          },
          {
            "$ref": "#/components/schemas/TurnstileSolution"
          }
        ],
        "description": "A task's answer. Its shape is the solution schema of the task's type (`<Type>Solution`, e.g. `RecaptchaV2Solution` for `recaptcha.v2`).",
        "type": "object"
      },
      "Task": {
        "properties": {
          "completed_at": {
            "description": "When the task became final; absent while processing.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "cost": {
            "$ref": "#/components/schemas/Money",
            "description": "What the task cost (zero unless solved and charged)."
          },
          "created_at": {
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "error": {
            "description": "Why the task failed when `status` is `failed`, else `null`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/TaskError"
              },
              {
                "type": "null"
              }
            ]
          },
          "id": {
            "description": "Task ID (a 53-bit integer as a string).",
            "examples": [
              "7259140378796032"
            ],
            "pattern": "^[0-9]+$",
            "type": "string"
          },
          "metadata": {
            "$ref": "#/components/schemas/Metadata"
          },
          "params": {
            "additionalProperties": true,
            "description": "The task's parameters with secrets removed (proxy login and password, cookies where the type marks\nthem sensitive) and strings longer than 256 bytes (images) replaced by `\"[N bytes]\"`. `null` when\nnot available.\n",
            "type": [
              "object",
              "null"
            ]
          },
          "sandbox": {
            "const": true,
            "description": "Present (true) on tasks created with a test key.",
            "type": "boolean"
          },
          "solution": {
            "description": "The answer when `status` is `solved`, else `null`. Its shape depends on `type`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/Solution"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "enum": [
              "processing",
              "solved",
              "failed"
            ],
            "type": "string"
          },
          "type": {
            "description": "Canonical task type, e.g. `recaptcha.v2` (see `CreateTaskRequest`).",
            "type": "string"
          }
        },
        "required": [
          "id",
          "type",
          "status",
          "params",
          "solution",
          "error",
          "cost",
          "created_at"
        ],
        "type": "object"
      },
      "TaskError": {
        "description": "| code | meaning |\n| --- | --- |\n| `unsolvable` | the captcha could not be solved (also when no solver accepts these parameters) |\n| `timeout` | not solved before the type's deadline |\n| `proxy_error` | the proxy could not be used |\n| `invalid_site` | the site key or domain is invalid |\n| `invalid_image` | the image is empty, too big or unreadable |\n| `cancelled` | the task was cancelled |\n\nNew codes may be added.\n",
        "properties": {
          "code": {
            "examples": [
              "unsolvable"
            ],
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "code",
          "message"
        ],
        "type": "object",
        "x-noptcha-codes": [
          "unsolvable",
          "timeout",
          "proxy_error",
          "invalid_site",
          "invalid_image",
          "cancelled"
        ]
      },
      "Token": {
        "description": "Token to submit to the target site. Single use.",
        "minLength": 1,
        "type": "string"
      },
      "TurnstileParams": {
        "additionalProperties": false,
        "properties": {
          "action": {
            "description": "The action option of the widget (data-action).",
            "maxLength": 256,
            "minLength": 1,
            "type": "string"
          },
          "cdata": {
            "description": "The cData option of the widget (data-cdata).",
            "maxLength": 1024,
            "minLength": 1,
            "type": "string"
          },
          "page_data": {
            "description": "The chlPageData value of a challenge page widget.",
            "maxLength": 8192,
            "minLength": 1,
            "type": "string"
          },
          "proxy": {
            "$ref": "#/components/schemas/Proxy"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent"
          },
          "website_key": {
            "$ref": "#/components/schemas/WebsiteKey"
          },
          "website_url": {
            "$ref": "#/components/schemas/WebsiteUrl"
          }
        },
        "required": [
          "website_url",
          "website_key"
        ],
        "title": "Cloudflare Turnstile parameters",
        "type": "object",
        "x-schema-version": 1
      },
      "TurnstileSolution": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "$ref": "#/components/schemas/Token"
          },
          "user_agent": {
            "$ref": "#/components/schemas/UserAgent",
            "description": "User-Agent the token was obtained with; use it when submitting the token."
          }
        },
        "required": [
          "token"
        ],
        "title": "Cloudflare Turnstile solution",
        "type": "object",
        "x-schema-version": 1
      },
      "TypeInfo": {
        "properties": {
          "family": {
            "description": "Captcha family (concurrency is limited per family), e.g. `recaptcha`, `hcaptcha`, `cloudflare`, `arkose`, `image`.",
            "type": "string"
          },
          "name": {
            "examples": [
              "reCAPTCHA v2"
            ],
            "type": "string"
          },
          "status": {
            "description": "`active` or `beta`.",
            "examples": [
              "active"
            ],
            "type": "string"
          },
          "timeout_seconds": {
            "description": "Deadline after which an unsolved task fails with `timeout`.",
            "type": "integer"
          },
          "type": {
            "examples": [
              "recaptcha.v2"
            ],
            "type": "string"
          },
          "variants": {
            "items": {
              "properties": {
                "price": {
                  "$ref": "#/components/schemas/Money"
                },
                "variant": {
                  "description": "`proxyless` or `proxy` (the task has `params.proxy`).",
                  "type": "string"
                }
              },
              "required": [
                "variant",
                "price"
              ],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "type",
          "family",
          "name",
          "status",
          "timeout_seconds",
          "variants"
        ],
        "type": "object"
      },
      "TypeList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/TypeInfo"
            },
            "type": "array"
          },
          "price_version": {
            "description": "Version of the price list the prices come from.",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "price_version"
        ],
        "type": "object"
      },
      "Usage": {
        "properties": {
          "currency": {
            "const": "USD",
            "type": "string"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/UsageRow"
            },
            "type": "array"
          },
          "from": {
            "description": "Effective start (after rounding and the 90-day limit of `group_by=key`).",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "granularity": {
            "enum": [
              "hour",
              "day"
            ],
            "type": "string"
          },
          "group_by": {
            "enum": [
              "type",
              "key"
            ],
            "type": "string"
          },
          "object": {
            "const": "usage",
            "type": "string"
          },
          "sandbox": {
            "description": "True for test keys (always an empty report).",
            "type": "boolean"
          },
          "to": {
            "description": "Effective end (exclusive).",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "totals": {
            "$ref": "#/components/schemas/UsageCounts"
          }
        },
        "required": [
          "object",
          "from",
          "to",
          "granularity",
          "group_by",
          "currency",
          "sandbox",
          "data",
          "totals"
        ],
        "type": "object"
      },
      "UsageCounts": {
        "properties": {
          "amount": {
            "$ref": "#/components/schemas/Amount",
            "description": "cash + promo."
          },
          "billed": {
            "description": "Tasks charged.",
            "type": "integer"
          },
          "cash": {
            "$ref": "#/components/schemas/Amount"
          },
          "promo": {
            "$ref": "#/components/schemas/Amount"
          },
          "unbilled": {
            "description": "Tasks not charged (unsolvable, timed out, cancelled).",
            "type": "integer"
          }
        },
        "required": [
          "billed",
          "unbilled",
          "amount",
          "cash",
          "promo"
        ],
        "type": "object"
      },
      "UsageRow": {
        "allOf": [
          {
            "$ref": "#/components/schemas/UsageCounts"
          },
          {
            "properties": {
              "end": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "key": {
                "description": "With `group_by=key`. `null` is the unattributed remainder (the difference between the ledger and the\nper-key task log; usually zero, briefly non-zero while events are being processed).\n",
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "properties": {
                      "hint": {
                        "description": "Prefix and last four characters, e.g. `nop_live_ab12…wxyz`.",
                        "type": "string"
                      },
                      "id": {
                        "type": "string"
                      },
                      "mode": {
                        "enum": [
                          "live",
                          "test"
                        ],
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "id"
                    ],
                    "type": "object"
                  }
                ]
              },
              "start": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "type": {
                "description": "With `group_by=type`.",
                "type": "string"
              },
              "variant": {
                "description": "With `group_by=type`.",
                "type": "string"
              }
            },
            "required": [
              "start",
              "end"
            ],
            "type": "object"
          }
        ],
        "description": "One period and type (`group_by=type`) or key (`group_by=key`)."
      },
      "UserAgent": {
        "description": "Browser User-Agent.",
        "maxLength": 1024,
        "minLength": 1,
        "type": "string"
      },
      "ValidationProblem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Problem"
          },
          {
            "properties": {
              "errors": {
                "description": "One entry per problem, sorted by `pointer`. At most 50 entries; when there are more, `detail` ends with\n\"and N more errors\".\n",
                "items": {
                  "$ref": "#/components/schemas/FieldError"
                },
                "maxItems": 50,
                "type": "array"
              }
            },
            "required": [
              "errors"
            ],
            "type": "object"
          }
        ],
        "description": "`invalid_params`, with one entry per problem (at most 50, sorted by pointer)."
      },
      "WebhookBalanceLowEvent": {
        "properties": {
          "data": {
            "properties": {
              "balance": {
                "$ref": "#/components/schemas/Amount",
                "description": "Cash + promotional credit when the balance was checked."
              },
              "currency": {
                "const": "USD",
                "type": "string"
              },
              "threshold": {
                "$ref": "#/components/schemas/Amount",
                "description": "The alert threshold set in the console."
              }
            },
            "required": [
              "balance",
              "threshold",
              "currency"
            ],
            "type": "object"
          },
          "timestamp": {
            "description": "When the balance was checked (just after a charge).",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "balance.low",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookKeyExpiringEvent": {
        "properties": {
          "data": {
            "properties": {
              "expires_at": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "id": {
                "description": "API key ID (as in the console).",
                "pattern": "^[0-9]+$",
                "type": "string"
              },
              "last4": {
                "type": "string"
              },
              "mode": {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "prefix": {
                "description": "The first characters of the key, as shown in the console.",
                "examples": [
                  "nop_live_ab12"
                ],
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "prefix",
              "last4",
              "mode",
              "expires_at"
            ],
            "type": "object"
          },
          "timestamp": {
            "description": "When the upcoming expiry was noticed.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "key.expiring",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookPaymentDisputedEvent": {
        "properties": {
          "data": {
            "properties": {
              "amount": {
                "$ref": "#/components/schemas/Amount",
                "description": "Amount in dispute."
              },
              "currency": {
                "const": "USD",
                "type": "string"
              },
              "id": {
                "description": "Dispute ID.",
                "pattern": "^[0-9]+$",
                "type": "string"
              },
              "opened_at": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "payment_id": {
                "description": "The disputed payment (top-up), `tp_…`.",
                "type": "string"
              }
            },
            "required": [
              "id",
              "payment_id",
              "amount",
              "currency",
              "opened_at"
            ],
            "type": "object"
          },
          "timestamp": {
            "description": "When the dispute was opened.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "payment.disputed",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookPaymentRefundedEvent": {
        "properties": {
          "data": {
            "properties": {
              "amount": {
                "$ref": "#/components/schemas/Amount",
                "description": "Amount refunded."
              },
              "currency": {
                "const": "USD",
                "type": "string"
              },
              "id": {
                "description": "Refund ID.",
                "pattern": "^[0-9]+$",
                "type": "string"
              },
              "payment_id": {
                "description": "The refunded payment (top-up), `tp_…`.",
                "type": "string"
              },
              "refunded_at": {
                "description": "When the refund first succeeded (does not change afterwards).",
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              }
            },
            "required": [
              "id",
              "payment_id",
              "amount",
              "currency",
              "refunded_at"
            ],
            "type": "object"
          },
          "timestamp": {
            "description": "When the refund succeeded.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "payment.refunded",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookPaymentSucceededEvent": {
        "properties": {
          "data": {
            "properties": {
              "amount": {
                "$ref": "#/components/schemas/Amount",
                "description": "Amount added to the balance."
              },
              "created_at": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "credited_at": {
                "format": "date-time",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
                "type": "string"
              },
              "currency": {
                "const": "USD",
                "type": "string"
              },
              "id": {
                "description": "The payment (top-up) ID shown in the console, `tp_…`.",
                "examples": [
                  "tp_3k9x0q2m8w1v7c5b4n6z"
                ],
                "type": "string"
              }
            },
            "required": [
              "id",
              "amount",
              "currency",
              "created_at",
              "credited_at"
            ],
            "type": "object"
          },
          "timestamp": {
            "description": "When the top-up was credited.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "payment.succeeded",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookTaskEvent": {
        "description": "A task event (`task.solved` or `task.failed`), Standard Webhooks' recommended envelope.",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Task"
          },
          "timestamp": {
            "description": "When the task became final.",
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "enum": [
              "task.solved",
              "task.failed"
            ],
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebhookTestEvent": {
        "properties": {
          "data": {
            "properties": {
              "endpoint_id": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "endpoint_id",
              "message"
            ],
            "type": "object"
          },
          "timestamp": {
            "format": "date-time",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$",
            "type": "string"
          },
          "type": {
            "const": "webhook.test",
            "type": "string"
          }
        },
        "required": [
          "type",
          "timestamp",
          "data"
        ],
        "type": "object"
      },
      "WebsiteKey": {
        "description": "The site key of the captcha widget.",
        "maxLength": 512,
        "minLength": 1,
        "type": "string"
      },
      "WebsiteUrl": {
        "description": "Full URL of the page that shows the captcha (http or https).",
        "format": "uri",
        "maxLength": 4096,
        "minLength": 8,
        "pattern": "^[Hh][Tt][Tt][Pp][Ss]?://",
        "type": "string"
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "description": "`Authorization: Bearer nop_live_…` (or `nop_test_…` for the sandbox). The compatibility API takes the\nsame key in the `clientKey` body field instead.\n",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "name": "Noptcha support",
      "url": "https://noptcha.com"
    },
    "description": "Noptcha routes each captcha task to the best available solver (our own models, third-party solving\nservices or vision models) and charges only for solved tasks. Prices are in US dollars.\n\nThere are two APIs on the same host. They share keys, prices, task state and limits.\n\n* **Compatibility API** (root paths such as `/createTask`): the anti-captcha compatible JSON protocol,\n  so existing software works by changing the host and the key. Every response is HTTP 200; check\n  `errorId` and `errorCode`. Task IDs are integers. The key goes in the `clientKey` body field.\n* **Native API** (`/v1/...`): REST + JSON with synchronous waiting (`Prefer: wait=N`), idempotent\n  task creation (`Idempotency-Key`), errors as RFC 9457 problem details, usage reports. Task IDs are\n  strings (the same number as in the compatibility API). The key goes in `Authorization: Bearer <key>`.\n\n## Keys\n\nKeys look like `nop_live_…` (live) or `nop_test_…` (sandbox): the prefix, 36 random base62 characters\nand a 4-character checksum. A key has scopes: `tasks:write` (create, poll and report tasks),\n`balance:read`, `usage:read`. `GET /v1/me` and `GET /v1/types` work with any valid key; `GET /v1/catalog`\nneeds no key at all. A key can be\nlimited to some task types, to client IP ranges, and to a spending budget per period.\n\nAfter 50 requests with invalid keys from one IP address (one IPv6 /64; 500 per IPv6 /48) within\n10 minutes, that IP is blocked for the rest of the window for keys we do not already know\n(`rate_limited` / `ERROR_IP_BLOCKED`). Valid keys keep working from that IP.\n\n## Sandbox (test keys)\n\n`nop_test_` keys never call a solver, never charge and never appear in usage. They return fixed answers\nso integrations, SDKs and documentation examples can run end to end:\n\n* token types return `NOPTCHA_TEST_TOKEN_<task id>` (with `user_agent: \"Mozilla/5.0 (Noptcha test)\"`\n  where the type has one); `funcaptcha` returns only the token; `cloudflare.challenge` returns\n  `{\"cookies\": {\"cf_clearance\": \"NOPTCHA_TEST_TOKEN_<id>\"}, \"user_agent\": …}`;\n  `image.text` returns `{\"text\": \"noptcha\"}`; image grid and image FunCaptcha types return `{\"objects\": [0]}`.\n* Magic values in `website_key` (compatibility API: `websiteKey`), `website_public_key`\n  (`websitePublicKey`) or `question` simulate outcomes:\n  `test-unsolvable…` fails with `unsolvable` (`ERROR_CAPTCHA_UNSOLVABLE`),\n  `test-timeout…` fails with `timeout` (`ERROR_CAPTCHA_UNSOLVABLE`),\n  `test-proxy-error…` fails with `proxy_error` (`ERROR_PROXY_CONNECT_REFUSED`),\n  `test-slow-<seconds>` stays `processing` for that many seconds (at most 90) and then succeeds.\n* Sandbox limits per organization: 10 tasks created per second (`rate_limited`,\n  `ERROR_NO_SLOT_AVAILABLE`), 20 tasks still processing (`concurrency_limited`), 20 synchronous waits per\n  API process (more waits return 202 at once). The per-key create limit applies too. Sandbox results are\n  kept for 10 minutes. Test keys see only sandbox tasks, live keys only live tasks.\n* Sandbox tasks carry `\"sandbox\": true`; `GET /v1/usage` returns an empty report with `\"sandbox\": true`.\n\n## Limits\n\nStarting values, subject to change (see `GET /v1/me` for the values that apply to a key):\n\n* Creating tasks: 200 per second per key, bursts of 200.\n* Polling one task: 5 per second, bursts of 10 (a long poll with `wait` counts once). The compatibility\n  API answers `processing` instead of an error when a task is polled too often.\n* Concurrency: 50 tasks in flight per organization and captcha family.\n* Synchronous waiting: at most 90 seconds.\n* Request body: 1 MB for image types, 64 KB for other types.\n* Images: base64 in the standard or URL-safe alphabet (not mixed), with or without `=` padding, line breaks\n  or spaces, optionally behind a `data:image/<type>;base64,` prefix; the image is passed on in standard base64.\n  Only complete, well-formed PNG, JPEG, GIF, WebP and BMP files are accepted (no multi-picture JPEG / MPO, at most\n  100 scans per JPEG), at most 8192 pixels per side and 8,388,608 (2^23) pixels in total, read from the file\n  structure (for GIF and WebP the largest of the canvas and every frame). Animated images (GIF, APNG, WebP)\n  count every frame as a full canvas: at most 1000 frames and 8,388,608 (2^23) pixels for frames x width x height; all images of one task together\n  at most 33,554,432 (2^25) pixels counted the same way.\n  Anything else is `422 invalid_params` with a pointer to the image (`/params/images/1`) and a\n  `reason` (`image_too_large`, `image_format`, `image_base64`, `image_empty`); in the compatibility API\n  `ERROR_TOO_BIG_CAPTCHA_FILESIZE`, `ERROR_IMAGE_TYPE_NOT_SUPPORTED` (format or base64) or\n  `ERROR_ZERO_CAPTCHA_FILESIZE`.\n* Results are kept for 10 minutes after a task completes; feedback is accepted in the same window.\n\n`429` and `503` responses carry `Retry-After` (seconds); wait that long before retrying.\n\n## Conventions\n\n* Every response carries `Noptcha-Request-Id`; include it when you contact support.\n* v1 and webhook times are RFC 3339 in UTC with exactly three fractional digits (milliseconds) and a `Z`\n  suffix, for example `2026-11-05T08:00:01.120Z` (trailing zeros are kept). Compatibility API times are\n  Unix seconds.\n* v1 money is a decimal string with 6 places plus `currency: \"USD\"`. The compatibility API returns\n  `balance` as a number and `cost` as a string, like anti-captcha.\n* v1 only changes in backward-compatible ways: new fields, endpoints, enum values, error codes and task\n  types can appear at any time. Clients must ignore unknown fields and accept unknown values.\n* An unknown path, or a known path with a method it does not support, is `404 not_found` (not 405).\n* Any request whose body is over 1 MB is `413 request_too_large`, whatever the method (GET included).\n\n## Webhooks\n\nNoptcha can POST a task's final result to you instead of (or as well as) you polling for it:\n\n* **Per task**: `callback_url` (v1) or `callbackUrl` (compatibility API) when you create the task. Live and\n  test keys both work; a sandbox task's callback is sent when its result is ready. The v1 body is the\n  `task.solved` / `task.failed` event below; the compatibility body is the `getTaskResult` response plus\n  `taskId` (see the `compatCallback` webhook).\n* **Organization endpoints**: configured in the console, each subscribed to some of these events and with\n  its own signing secret:\n  * `task.solved`, `task.failed`: a live task's final result (sandbox tasks are only sent to their own\n    callback URL);\n  * `balance.low`: the balance (cash + promotional credit) fell below the alert threshold you set in the\n    console, at most once per 24 hours (also emailed to owners, admins and billing members);\n  * `payment.succeeded`, `payment.refunded`, `payment.disputed`: a top-up was credited, a refund of a top-up\n    succeeded (one message per refund), a top-up was disputed (chargeback);\n  * `key.expiring`: an API key with an expiry date expires within 7 days (also emailed to owners and admins).\n\nRequests follow [Standard Webhooks](https://www.standardwebhooks.com/): `POST` with a JSON body and the\nheaders `webhook-id` (the same for every retry and manual resend of a message: use it to deduplicate),\n`webhook-timestamp` (Unix seconds when this attempt was sent) and `webhook-signature`\n(`v1,<base64 HMAC-SHA256 of \"<webhook-id>.<webhook-timestamp>.<body>\">`; several space-separated\nsignatures during a secret rotation, accept the request if any one matches). Secrets look like\n`whsec_<base64 of 32 bytes>`; HMAC with the decoded 32 bytes. Per-task callbacks are signed with your\norganization's default webhook secret (shown in the console); endpoints with their own secret. After a\nrotation the previous secret keeps signing for 24 hours. Reject requests whose timestamp is more than a\nfew minutes old.\n\n* Any 2xx response acknowledges the message; anything else, a redirect, or no complete response within\n  5 seconds is a failure. Redirects are not followed.\n* Task events are retried 5, 25, 60, 150 and 300 seconds after a failure (±10%), and not after 10 minutes\n  (results are only kept for 10 minutes). Sandbox callbacks are tried at most twice. Other events are\n  retried 8 times within 24 hours (5 s, 5 min, 30 min, 1 h, 2 h, 4 h, 8 h, 8 h). Messages can arrive\n  more than once and out of order; `webhook-id` is fixed per event (for example one per refund), so\n  deduplicate on it.\n* Callback URLs must be `http` or `https` on port 80, 443, 8080 or 8443, at most 2048 bytes, without\n  user info or fragment, and must resolve to public addresses only. URLs that break these rules when the\n  task is created are rejected (`422 invalid_params` with pointer `/callback_url`;\n  `ERROR_INCORRECT_SESSION_DATA`); a host that resolves to a non-public address at delivery time is not\n  contacted.\n* An endpoint that keeps failing for 24 hours is disabled (owners and admins are emailed); re-enable it\n  in the console.\n",
    "summary": "Captcha solving API with an anti-captcha compatible protocol and a native REST API (v1).",
    "title": "Noptcha API",
    "version": "1.0.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/createTask": {
      "post": {
        "description": "Creates a task and returns its integer `taskId`; poll it with `/getTaskResult`.\n\nWhen the solver answers synchronously (image types on our own models), the response already has\n`status: \"ready\"`, `solution` and `cost`; polling it afterwards returns the same result. When such a\nsynchronous attempt fails, the response is the task's error (for example `ERROR_CAPTCHA_UNSOLVABLE`)\nand no task ID is returned; nothing is charged.\n\n`softId` / `appId` (digits) are recorded with the task for the developer programme.\n",
        "operationId": "compatCreateTask",
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "clientKey": "nop_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
                "task": {
                  "type": "RecaptchaV2TaskProxyless",
                  "websiteKey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
                  "websiteURL": "https://example.com/login"
                }
              },
              "schema": {
                "$ref": "#/components/schemas/CompatCreateTaskRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/CompatCreateTaskResult"
                    },
                    {
                      "$ref": "#/components/schemas/CompatError"
                    }
                  ]
                }
              }
            },
            "description": "Created (`errorId` 0) or rejected (`errorId` 1).",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Create a task",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/getBalance": {
      "post": {
        "description": "Available balance in US dollars (needs the `balance:read` scope).",
        "operationId": "compatGetBalance",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompatKeyRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/CompatBalance"
                    },
                    {
                      "$ref": "#/components/schemas/CompatError"
                    }
                  ]
                }
              }
            },
            "description": "Balance or an error.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Get the balance",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/getTaskResult": {
      "post": {
        "description": "Returns `status: \"processing\"` until the task completes, then `status: \"ready\"` with the solution, or\nthe task's error (`errorId` 1). Results are kept for 10 minutes after completion; after that, and for\ntasks of other organizations, the answer is `ERROR_NO_SUCH_CAPCHA_ID`.\n\nPolling one task more than 5 times per second (bursts of 10) is answered with `processing` instead\nof an error, so clients keep polling. Likewise, when the API is momentarily at capacity, polling is\nanswered with `processing` (the other compatibility endpoints answer `ERROR_NO_SLOT_AVAILABLE`; a\nrejected `/createTask` charges nothing and can be resent). Poll every 1–3 seconds.\n",
        "operationId": "compatGetTaskResult",
        "requestBody": {
          "$ref": "#/components/requestBodies/CompatTaskRequest"
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/CompatTaskProcessing"
                    },
                    {
                      "$ref": "#/components/schemas/CompatTaskReady"
                    },
                    {
                      "$ref": "#/components/schemas/CompatError"
                    }
                  ]
                }
              }
            },
            "description": "Processing, ready, or an error.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Get a task's result",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/reportCorrectRecaptcha": {
      "post": {
        "description": "Reports whether a solved task's answer worked. Accepted for solved tasks within 10 minutes after\ncompletion; only the first report per task counts, later ones still succeed. Reports are recorded as a quality signal;\nthey do not refund the task. Unsolved or unknown tasks: `ERROR_NO_SUCH_CAPCHA_ID`.\n",
        "operationId": "compatReportCorrectRecaptcha",
        "requestBody": {
          "$ref": "#/components/requestBodies/CompatTaskRequest"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CompatReport"
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Report a correct token",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/reportIncorrectImageCaptcha": {
      "post": {
        "description": "Reports whether a solved task's answer worked. Accepted for solved tasks within 10 minutes after\ncompletion; only the first report per task counts, later ones still succeed. Reports are recorded as a quality signal;\nthey do not refund the task. Unsolved or unknown tasks: `ERROR_NO_SUCH_CAPCHA_ID`.\n",
        "operationId": "compatReportIncorrectImageCaptcha",
        "requestBody": {
          "$ref": "#/components/requestBodies/CompatTaskRequest"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CompatReport"
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Report a wrong image answer",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/reportIncorrectRecaptcha": {
      "post": {
        "description": "Reports whether a solved task's answer worked. Accepted for solved tasks within 10 minutes after\ncompletion; only the first report per task counts, later ones still succeed. Reports are recorded as a quality signal;\nthey do not refund the task. Unsolved or unknown tasks: `ERROR_NO_SUCH_CAPCHA_ID`.\n",
        "operationId": "compatReportIncorrectRecaptcha",
        "requestBody": {
          "$ref": "#/components/requestBodies/CompatTaskRequest"
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CompatReport"
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [],
        "summary": "Report a wrong token",
        "tags": [
          "Compatibility"
        ]
      }
    },
    "/v1/balance": {
      "get": {
        "description": "The organization's balance (needs `balance:read`).",
        "operationId": "getBalance",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            },
            "description": "Balance.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get the balance",
        "tags": [
          "Account"
        ]
      }
    },
    "/v1/catalog": {
      "get": {
        "description": "The public task types with their list prices, for price tables and integrations that have no key yet.\nNo authentication: the `Authorization` header is ignored (a valid, invalid or missing key gets the same\nresponse, and is not checked or counted against the IP). The items have the same shape as `GET /v1/types`,\nbut list every public type at the list price, whatever an organization's actual prices or a key's\nallowed types; use `GET /v1/types` for the prices that apply to you.\n\n`placeholder` is `true` when the prices are not real prices (test deployments only); do not show them as\nprices then.\n\nCacheable: `Cache-Control: public, max-age=300`, a strong `ETag`; send it back in `If-None-Match` to get\n`304 Not Modified`. `HEAD` works as well.\n\nCross-origin reads are allowed from any origin: every response on this path, errors included, has\n`Access-Control-Allow-Origin: *` and exposes `ETag`, `Retry-After` and `Noptcha-Request-Id`. There is no\nCORS preflight (`OPTIONS` is not served), so from a browser send a simple request: a plain `fetch(url)`, or\nonly CORS-safelisted headers such as `Accept`; a request with `Authorization` or another custom header is\nblocked by the browser. The SDKs' `get_catalog` / `getCatalog` send only `Accept` (no key, and the\nTypeScript SDK no `User-Agent`).\n\nRate limit per client IP: 60 per minute, bursts of 30; for IPv6 per /64, and also 600 per minute, bursts of\n300, per /48 (starting values). Over that `429 rate_limited` with `Retry-After`.\n",
        "operationId": "getCatalog",
        "parameters": [
          {
            "description": "An `ETag` from an earlier response (or a list of them, or `*`); `304` when it still matches.",
            "in": "header",
            "name": "If-None-Match",
            "schema": {
              "examples": [
                "\"5d41402abc4b2a76b9719d911017c592\""
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalog"
                }
              }
            },
            "description": "The catalog.",
            "headers": {
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CatalogAllowOrigin"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CatalogCacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/CatalogETag"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "304": {
            "description": "Not modified (`If-None-Match` matched the current `ETag`); no body.",
            "headers": {
              "Access-Control-Allow-Origin": {
                "$ref": "#/components/headers/CatalogAllowOrigin"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CatalogCacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/CatalogETag"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/EdgeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "security": [],
        "summary": "Get the public catalog and list prices",
        "tags": [
          "Account"
        ]
      }
    },
    "/v1/me": {
      "get": {
        "description": "The key's organization, settings, budget (with what is used in the current period) and the limits that\napply to it. Any valid key may call this. The response never contains the key itself.\n",
        "operationId": "getMe",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            },
            "description": "The key.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Describe the current key",
        "tags": [
          "Account"
        ]
      }
    },
    "/v1/tasks": {
      "post": {
        "description": "Creates a task. A task that is already final (solved or failed) is returned with **200**; a task that\nis still processing with **202**. Both carry `Location: /v1/tasks/{id}`.\n\n**Synchronous waiting.** With `Prefer: wait=N` (or `?wait=N`), the request waits up to N seconds\n(at most 90) for the result: 200 if the task completes in time, otherwise 202 and you poll\n`GET /v1/tasks/{id}`. `Preference-Applied: wait=N` confirms the wait (N capped at 90). Types solved\nsynchronously return the result at once anyway. When an organization already has too many waiting\nrequests, the request returns 202 without waiting and without `Preference-Applied`.\n\n**Idempotency.** With `Idempotency-Key` (1–64 visible ASCII characters, kept for 24 hours per organization),\nretrying the same request returns the same task instead of creating and charging a new one; replayed\nresponses carry `Idempotent-Replayed: true`. The same key with a body that is not byte-for-byte identical (serialize once, resend the same bytes) is `409\nidempotency_conflict`; so is a retry while the first request with that key is still being admitted\n(retry shortly). When the first request did not create a task (insufficient balance, no capacity,\ninvalid parameters…) the key is released and can be reused. After the task's result has expired\n(10 minutes after completion) a replay is `404 not_found`: the task is not created again, use a new key.\n\n**Failures.** A task that cannot be solved is a successful request: 200 with `status: \"failed\"`,\n`error.code` and zero cost. `503 service_unavailable` means no solver could take the task right now;\nnothing was created or charged.\n\n**Callbacks.** With `callback_url`, the final result is also POSTed there as a `task.solved` or\n`task.failed` event (see Webhooks). An invalid URL is `422 invalid_params` with pointer `/callback_url`\nand no task is created; a `callback_url` that is not a string is `400 invalid_request`. `null` and `\"\"`\nmean no callback.\n\nEvery response passes through the per-key create limit and carries `RateLimit-Policy` and\n`RateLimit` (when rate limiting is enabled), including errors after authentication.\n",
        "operationId": "createTask",
        "parameters": [
          {
            "$ref": "#/components/parameters/Prefer"
          },
          {
            "$ref": "#/components/parameters/Wait"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "metadata": {
                  "order": "A-17"
                },
                "params": {
                  "website_key": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
                  "website_url": "https://example.com/login"
                },
                "type": "recaptcha.v2"
              },
              "schema": {
                "$ref": "#/components/schemas/CreateTaskRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            },
            "description": "The task is final (solved or failed).",
            "headers": {
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              },
              "Preference-Applied": {
                "$ref": "#/components/headers/Preference-Applied"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            },
            "description": "The task is still processing; poll `Location`.",
            "headers": {
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              },
              "Preference-Applied": {
                "$ref": "#/components/headers/Preference-Applied"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableContent"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Create a task",
        "tags": [
          "Tasks"
        ]
      }
    },
    "/v1/tasks/{id}": {
      "get": {
        "description": "Returns the task: 200 when final, 202 while processing. With `?wait=N` (or `Prefer: wait=N`) this\nis a long poll of up to N seconds (at most 90) that returns as soon as the task completes. Unknown and\nexpired tasks, tasks of other organizations, and sandbox tasks asked with a live key (or the reverse)\nare `404`.\n\nOne task may be polled 5 times per second (bursts of 10); a long poll counts once. Over the limit:\n`429 rate_limited` with `Retry-After` and `RateLimit-Policy: \"poll\";q=10;w=2`. When the server already\nhas too many waiting requests, a long poll returns `processing` at once (without\n`Preference-Applied`); wait a second before asking again.\n",
        "operationId": "getTask",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          },
          {
            "$ref": "#/components/parameters/Wait"
          },
          {
            "$ref": "#/components/parameters/Prefer"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            },
            "description": "The task is final.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              },
              "Preference-Applied": {
                "$ref": "#/components/headers/Preference-Applied"
              }
            }
          },
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Task"
                }
              }
            },
            "description": "The task is still processing.",
            "headers": {
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              },
              "Preference-Applied": {
                "$ref": "#/components/headers/Preference-Applied"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get a task",
        "tags": [
          "Tasks"
        ]
      }
    },
    "/v1/tasks/{id}/feedback": {
      "post": {
        "description": "Tells us whether a solved task's answer was accepted by the target site. Accepted for solved tasks\nwithin 10 minutes after completion; only the first report per task counts, later ones still return\n200. Feedback is recorded as a quality signal; it does not refund the task. A task that is not solved (processing or\nfailed) is `409 task_not_solved`. `reason` is optional and is not stored.\n",
        "operationId": "sendTaskFeedback",
        "parameters": [
          {
            "$ref": "#/components/parameters/TaskId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResult"
                }
              }
            },
            "description": "Recorded.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Report whether an answer worked",
        "tags": [
          "Tasks"
        ]
      }
    },
    "/v1/types": {
      "get": {
        "description": "The public task types this key may use, with the organization's actual price per variant. Types\nwithout a price are left out; `data` is an empty array when none is left. Any valid key may call this,\nwhatever its scopes.\n",
        "operationId": "listTypes",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TypeList"
                }
              }
            },
            "description": "Types and prices.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "List task types and prices",
        "tags": [
          "Account"
        ]
      }
    },
    "/v1/usage": {
      "get": {
        "description": "Task counts and amounts per hour or day, by task type or by key (needs `usage:read`). Amounts are what\nwas actually taken from the balance, after corrections. Only periods with data are returned (no zero\nrows), ordered by time and then type or key; the rows always add up to `totals`.\n\n`from` is rounded down and `to` up to period boundaries (`to` is exclusive). Without `to`: the end of the\ncurrent period; without `from`: 24 hours (hourly) or 30 days (daily) before `to`. Ranges: hourly at most\n7 days, daily at most 92 days; `from` not before 2026-01-01 and not in the future. `group_by=key` covers\nthe last 90 days only: an earlier `from` is moved to the first available day (the response shows the\neffective `from`), a range entirely before that is `400`. Results over 10,000 rows (or over the query's\nresource limits) are `400` instead of being truncated; narrow the range or use `granularity=day`.\nEach parameter may be given once.\n\nRate limit per organization: 20 per minute, bursts of 5 (test keys counted separately), with\n`RateLimit-Policy: \"usage\";q=20;w=60`. `503` when usage is temporarily unavailable (or only the per-key\nbreakdown is, then with `Retry-After: 30`; `group_by=type` still works) and when too many usage queries\nare running (`Retry-After: 5`).\n\nTest keys get an empty report with `\"sandbox\": true` (parameters are still checked and rate limited).\n",
        "operationId": "getUsage",
        "parameters": [
          {
            "description": "Start, RFC 3339 or `YYYY-MM-DD` (UTC).",
            "in": "query",
            "name": "from",
            "schema": {
              "examples": [
                "2026-11-01",
                "2026-11-05T08:00:00Z"
              ],
              "type": "string"
            }
          },
          {
            "description": "End (exclusive), RFC 3339 or `YYYY-MM-DD` (UTC).",
            "in": "query",
            "name": "to",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "granularity",
            "schema": {
              "default": "day",
              "enum": [
                "hour",
                "day"
              ],
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "group_by",
            "schema": {
              "default": "type",
              "enum": [
                "type",
                "key"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            },
            "description": "Usage.",
            "headers": {
              "Noptcha-Request-Id": {
                "$ref": "#/components/headers/Noptcha-Request-Id"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimit-Policy"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "413": {
            "$ref": "#/components/responses/ContentTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get usage",
        "tags": [
          "Account"
        ]
      }
    }
  },
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "servers": [
    {
      "url": "https://api.noptcha.com"
    }
  ],
  "tags": [
    {
      "description": "The anti-captcha compatible JSON protocol.\n\n* Requests are `POST` with a JSON body. `Content-Type` is not required; the body is always parsed as JSON.\n* The key goes in `clientKey`. The key is checked before anything else, so an invalid key is reported\n  even when other fields are wrong.\n* Responses are always HTTP 200. `errorId` is 0 on success and 1 on error; then `errorCode` and\n  `errorDescription` say what went wrong (see `CompatError` for every code).\n* Two responses come from the infrastructure, not from the protocol: `403` (problem details, code\n  `forbidden`) when a request reaches the API without passing through our edge network, and `500`\n  (code `internal`) on an unexpected server error. Treat both as transient errors.\n* An unknown path, or a known path with another method (for example `GET /createTask`), is `404`\n  (problem details, code `not_found`).\n* Task type names are the common anti-captcha compatible names (case-insensitive); each maps to a\n  canonical type and variant, see `CompatTaskType`.\n* `callbackUrl` (optional) receives the final result as a POST (see Webhooks and the `compatCallback`\n  webhook). An invalid URL is `ERROR_INCORRECT_SESSION_DATA` and no task is created.\n",
      "name": "Compatibility"
    },
    {
      "description": "Create and poll tasks, report wrong answers (native API).",
      "name": "Tasks"
    },
    {
      "description": "Balance, task types and prices, the key itself, usage, the public catalog (native API).",
      "name": "Account"
    }
  ],
  "webhooks": {
    "balance.low": {
      "post": {
        "description": "Sent to endpoints subscribed to `balance.low` when a task's charge leaves the balance (cash +\npromotional credit) below the alert threshold set in the console (0 turns it off). The current balance\nis read again just before the message is created: if it is back at or above the threshold (for example\nyou just topped up), nothing is sent. At most once per 24 hours per organization: while the balance\nstays low you get one message a day; a top-up does not reset the 24 hours, raising the threshold does.\nTest keys never trigger it. `webhook-id` is `msg_bl_<organization id>_<unix seconds>`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "balance": "4.500000",
                  "currency": "USD",
                  "threshold": "5.000000"
                },
                "timestamp": "2026-11-05T08:00:07.456Z",
                "type": "balance.low"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookBalanceLowEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "The balance is low"
      }
    },
    "compatCallback": {
      "post": {
        "description": "Sent to the `callbackUrl` given to `/createTask`: the `getTaskResult` response for the final result plus\n`taskId`, signed like the other webhooks (verify it if your client can; if not, treat it as a signal and confirm with `getTaskResult`). `webhook-id` is `msg_t<task id>_cb`\n(`msg_s<task id>_cb` for sandbox tasks, whose body also has `\"sandbox\": true`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompatCallback"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "Compatibility API callback"
      }
    },
    "key.expiring": {
      "post": {
        "description": "An active API key with an expiry date expires within 7 days (keys still working during a rotation's\ngrace period are not included). One message per key and expiry date: changing the expiry date sends\na new one. `webhook-id` is `msg_ke_<key id>_<expiry as unix seconds>`; `timestamp` is when the\nexpiry was noticed.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "expires_at": "2026-11-10T00:00:00.000Z",
                  "id": "12",
                  "last4": "wxyz",
                  "mode": "live",
                  "name": "ci",
                  "prefix": "nop_live_ab12"
                },
                "timestamp": "2026-11-05T08:05:00.000Z",
                "type": "key.expiring"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookKeyExpiringEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "An API key expires soon"
      }
    },
    "payment.disputed": {
      "post": {
        "description": "The card issuer opened a dispute (chargeback) on a top-up. One message per dispute, sent when it is\nopened (not when it is resolved); `webhook-id` is `msg_pd_<dispute id>`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "amount": "20.000000",
                  "currency": "USD",
                  "id": "7",
                  "opened_at": "2026-11-07T03:00:00.000Z",
                  "payment_id": "tp_3k9x0q2m8w1v7c5b4n6z"
                },
                "timestamp": "2026-11-07T03:00:00.000Z",
                "type": "payment.disputed"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookPaymentDisputedEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "A top-up was disputed"
      }
    },
    "payment.refunded": {
      "post": {
        "description": "A refund of a top-up succeeded (refunds requested from support and refunds made by the payment\nprovider alike). One message per refund, so a top-up refunded in two parts sends two; `webhook-id`\nis `msg_pr_<refund id>`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "amount": "5.000000",
                  "currency": "USD",
                  "id": "41",
                  "payment_id": "tp_3k9x0q2m8w1v7c5b4n6z",
                  "refunded_at": "2026-11-06T10:12:00.000Z"
                },
                "timestamp": "2026-11-06T10:12:00.000Z",
                "type": "payment.refunded"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookPaymentRefundedEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "A refund succeeded"
      }
    },
    "payment.succeeded": {
      "post": {
        "description": "A top-up was paid and its amount added to the balance. One message per top-up; `webhook-id` is\n`msg_ps_<payment id>`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "amount": "20.000000",
                  "created_at": "2026-11-05T07:58:40.120Z",
                  "credited_at": "2026-11-05T08:00:07.456Z",
                  "currency": "USD",
                  "id": "tp_3k9x0q2m8w1v7c5b4n6z"
                },
                "timestamp": "2026-11-05T08:00:07.456Z",
                "type": "payment.succeeded"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookPaymentSucceededEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "A top-up was credited"
      }
    },
    "task.failed": {
      "post": {
        "description": "Like `task.solved`, for a task that ended without a solution (`data.status` is `failed`, `data.error` says why).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTaskEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "A task failed"
      }
    },
    "task.solved": {
      "post": {
        "description": "Sent to a v1 task's `callback_url` and to organization endpoints subscribed to `task.solved`. `data` is the\ntask object exactly as `GET /v1/tasks/{id}` returns it. `webhook-id` is `msg_t<task id>` for endpoints,\n`msg_t<task id>_cb` for a live task's callback and `msg_s<task id>_cb` for a sandbox task's callback.\nThe compatibility API's `callbackUrl` gets a different body, see `compatCallback`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "example": {
                "data": {
                  "completed_at": "2026-11-05T08:00:07.456Z",
                  "cost": {
                    "amount": "0.001000",
                    "currency": "USD"
                  },
                  "created_at": "2026-11-05T08:00:01.120Z",
                  "error": null,
                  "id": "7259140378796032",
                  "params": {
                    "website_key": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
                    "website_url": "https://example.com/login"
                  },
                  "solution": {
                    "token": "03AFcWeA…",
                    "user_agent": "Mozilla/5.0 …"
                  },
                  "status": "solved",
                  "type": "recaptcha.v2"
                },
                "timestamp": "2026-11-05T08:00:07.456Z",
                "type": "task.solved"
              },
              "schema": {
                "$ref": "#/components/schemas/WebhookTaskEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message; the response body is ignored."
          }
        },
        "summary": "A task was solved"
      }
    },
    "webhook.test": {
      "post": {
        "description": "Sent to one endpoint when you press \"Send test event\" in the console. Never retried.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookId"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestamp"
          },
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookTestEvent"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Any 2xx status acknowledges the message."
          }
        },
        "summary": "Test event"
      }
    }
  }
}
