# Create a task

> POST /v1/tasks: Create a task. Noptcha API reference.

Source: https://noptcha.com/docs/api-reference/create-task/

POST https://api.noptcha.com/v1/tasks

Native API (v1). [Guide](https://noptcha.com/docs/native-api.md). Operation ID `createTask`.

Creates a task. A task that is already final (solved or failed) is returned with **200**; a task that is still processing with **202**. Both carry `Location: /v1/tasks/{id}`.

**Synchronous waiting.** With `Prefer: wait=N` (or `?wait=N`), the request waits up to N seconds (at most 90) for the result: 200 if the task completes in time, otherwise 202 and you poll `GET /v1/tasks/{id}`. `Preference-Applied: wait=N` confirms the wait (N capped at 90). Types solved synchronously return the result at once anyway. When an organization already has too many waiting requests, the request returns 202 without waiting and without `Preference-Applied`.

**Idempotency.** With `Idempotency-Key` (1–64 visible ASCII characters, kept for 24 hours per organization), retrying the same request returns the same task instead of creating and charging a new one; replayed responses 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 idempotency_conflict`; so is a retry while the first request with that key is still being admitted (retry shortly). When the first request did not create a task (insufficient balance, no capacity, invalid parameters…) the key is released and can be reused. After the task's result has expired (10 minutes after completion) a replay is `404 not_found`: the task is not created again, use a new key.

**Failures.** A task that cannot be solved is a successful request: 200 with `status: "failed"`, `error.code` and zero cost. `503 service_unavailable` means no solver could take the task right now; nothing was created or charged.

**Callbacks.** With `callback_url`, the final result is also POSTed there as a `task.solved` or `task.failed` event (see Webhooks). An invalid URL is `422 invalid_params` with pointer `/callback_url` and no task is created; a `callback_url` that is not a string is `400 invalid_request`. `null` and `""` mean no callback.

Every response passes through the per-key create limit and carries `RateLimit-Policy` and `RateLimit` (when rate limiting is enabled), including errors after authentication.

## Request

Authentication: `Authorization: Bearer <key>` ([Keys](https://noptcha.com/docs/authentication.md)).

| Parameter | In | Description |
| --- | --- | --- |
| `Prefer`  optional  | header |  `wait=N`: wait up to N seconds (capped at 90) for the result, RFC 7240.  string · e.g. wait=60  |
| `wait`  optional  | query |  Seconds to wait for the result (capped at 90). Takes precedence over `Prefer: wait`. Values that are not a non-negative integer are ignored.  integer · ≥ 0  |
| `Idempotency-Key`  optional  | header |  1–64 visible ASCII characters (`!` to `~`, no spaces), unique per logical request; kept for 24 hours. Anything else is `400 invalid_request`.  string · pattern: ^\[!-~\]{1,64}$ · e.g. 3f6c2b9e-8d41-4a7f-b0c5-1e2d3a4b5c6d  |

Body (`application/json`, required):

One of (selected by `type`):

-   [`CreateCloudflareChallengeTaskRequest`](https://noptcha.com/docs/task-types/cloudflare-challenge.md) — Cloudflare challenge page (`cloudflare.challenge`, family `cloudflare`, active). Variants: `proxy` (`params.proxy` is required). Tasks not solved within 120 seconds fail with `timeout`.
-   [`CreateFuncaptchaTaskRequest`](https://noptcha.com/docs/task-types/funcaptcha.md) — 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`.
-   [`CreateHcaptchaTaskRequest`](https://noptcha.com/docs/task-types/hcaptcha.md) — 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`.
-   [`CreateImageFuncaptchaTaskRequest`](https://noptcha.com/docs/task-types/image-funcaptcha.md) — FunCaptcha image (`image.funcaptcha`, family `image`, beta). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.
-   [`CreateImageGridAwsTaskRequest`](https://noptcha.com/docs/task-types/image-grid-aws.md) — AWS WAF image grid (`image.grid.aws`, family `image`, beta). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.
-   [`CreateImageGridHcaptchaTaskRequest`](https://noptcha.com/docs/task-types/image-grid-hcaptcha.md) — hCaptcha image grid (`image.grid.hcaptcha`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.
-   [`CreateImageGridRecaptchaTaskRequest`](https://noptcha.com/docs/task-types/image-grid-recaptcha.md) — reCAPTCHA image grid (`image.grid.recaptcha`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.
-   [`CreateImageTextTaskRequest`](https://noptcha.com/docs/task-types/image-to-text.md) — Image to text (`image.text`, family `image`, active). Variants: `proxyless`. Tasks not solved within 60 seconds fail with `timeout`.
-   [`CreateRecaptchaV2TaskRequest`](https://noptcha.com/docs/task-types/recaptcha-v2.md) — 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`.
-   [`CreateRecaptchaV2EnterpriseTaskRequest`](https://noptcha.com/docs/task-types/recaptcha-v2-enterprise.md) — 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`.
-   [`CreateRecaptchaV3TaskRequest`](https://noptcha.com/docs/task-types/recaptcha-v3.md) — reCAPTCHA v3 (`recaptcha.v3`, family `recaptcha`, active). Variants: `proxyless`. Tasks not solved within 120 seconds fail with `timeout`.
-   [`CreateRecaptchaV3EnterpriseTaskRequest`](https://noptcha.com/docs/task-types/recaptcha-v3-enterprise.md) — reCAPTCHA v3 Enterprise (`recaptcha.v3.enterprise`, family `recaptcha`, active). Variants: `proxyless`. Tasks not solved within 120 seconds fail with `timeout`.
-   [`CreateTurnstileTaskRequest`](https://noptcha.com/docs/task-types/turnstile.md) — 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`.

Example

```json
{
  "metadata": {
    "order": "A-17"
  },
  "params": {
    "website_key": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
    "website_url": "https://example.com/login"
  },
  "type": "recaptcha.v2"
}
```

## Responses

### 200

The task is final (solved or failed).

Headers: `Idempotent-Replayed` (optional), `Location` (optional), `Noptcha-Request-Id`, `Preference-Applied` (optional), `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/json`

| Field | Type | Description |
| --- | --- | --- |
| `completed_at`  optional  | `string` |  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$  |
| `cost`  required  | `object` |  What the task cost (zero unless solved and charged).  |
| `cost.amount`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `cost.currency`  required  | `const "USD"` |  |
| `created_at`  required  | `string` |  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$  |
| `error`  required  | `one of | null` |  Why the task failed when `status` is `failed`, else `null`.  one of: `TaskError`  |
| `id`  required  | `string` |  Task ID (a 53-bit integer as a string).  pattern: ^\[0-9\]+$  |
| `metadata`  optional  | `object` |  Your own key-value pairs, returned with the task. At most 16 keys; keys 1–64 characters, values strings of at most 256 characters (Unicode code points, as JSON Schema counts them). A value that is not a string is `422 invalid_params` with pointer `/metadata/<key>`.  max 16 keys  |
| `metadata.<any key>`  optional  | `string` |  max length 256  |
| `params`  required  | `object | null` |  The task's parameters with secrets removed (proxy login and password, cookies where the type marks them sensitive) and strings longer than 256 bytes (images) replaced by `"[N bytes]"`. `null` when not available.  |
| `sandbox`  optional  | `const true` |  Present (true) on tasks created with a test key.  |
| `solution`  required  | `one of | null` |  The answer when `status` is `solved`, else `null`. Its shape depends on `type`.  one of: `Solution`  |
| `status`  required  | `enum` |  one of "processing", "solved", "failed"  |
| `type`  required  | `string` |  Canonical task type, e.g. `recaptcha.v2` (see `CreateTaskRequest`).  |

### 202

The task is still processing; poll `Location`.

Headers: `Idempotent-Replayed` (optional), `Location` (optional), `Noptcha-Request-Id`, `Preference-Applied` (optional), `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/json`

| Field | Type | Description |
| --- | --- | --- |
| `completed_at`  optional  | `string` |  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$  |
| `cost`  required  | `object` |  What the task cost (zero unless solved and charged).  |
| `cost.amount`  required  | `string` |  Decimal US dollars with 6 places.  pattern: ^-?\[0-9\]+\\.\[0-9\]{6}$  |
| `cost.currency`  required  | `const "USD"` |  |
| `created_at`  required  | `string` |  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$  |
| `error`  required  | `one of | null` |  Why the task failed when `status` is `failed`, else `null`.  one of: `TaskError`  |
| `id`  required  | `string` |  Task ID (a 53-bit integer as a string).  pattern: ^\[0-9\]+$  |
| `metadata`  optional  | `object` |  Your own key-value pairs, returned with the task. At most 16 keys; keys 1–64 characters, values strings of at most 256 characters (Unicode code points, as JSON Schema counts them). A value that is not a string is `422 invalid_params` with pointer `/metadata/<key>`.  max 16 keys  |
| `metadata.<any key>`  optional  | `string` |  max length 256  |
| `params`  required  | `object | null` |  The task's parameters with secrets removed (proxy login and password, cookies where the type marks them sensitive) and strings longer than 256 bytes (images) replaced by `"[N bytes]"`. `null` when not available.  |
| `sandbox`  optional  | `const true` |  Present (true) on tasks created with a test key.  |
| `solution`  required  | `one of | null` |  The answer when `status` is `solved`, else `null`. Its shape depends on `type`.  one of: `Solution`  |
| `status`  required  | `enum` |  one of "processing", "solved", "failed"  |
| `type`  required  | `string` |  Canonical task type, e.g. `recaptcha.v2` (see `CreateTaskRequest`).  |

### 400

`invalid_request`: the body is not valid JSON or misses a field, a parameter is wrong, `callback_url` is not a string, the result would be too large (usage). `unsupported_type`: the task type does not exist or is not available.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 401

`unauthorized`: the key is malformed, unknown, revoked or expired.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 402

`insufficient_balance` or `budget_exceeded` (the key's spending budget for the period is used up).

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 403

`forbidden`: the key lacks the scope this endpoint needs, the client IP is not in the key's allowlist, the key may not use this task type, or the organization is suspended (`detail` says which). Also returned, without `detail`, when the request did not pass through our edge network.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 404

`not_found`: no such task, it expired (results are kept 10 minutes after completion) or it belongs to another organization; or the task created with this `Idempotency-Key` has expired.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 409

`idempotency_conflict`: the `Idempotency-Key` was used with a different body, or the first request with it is still being processed (retry shortly). `task_not_solved`: feedback for a task that is not solved (still processing, or failed).

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 413

`request_too_large`: the body exceeds the limit (1 MB for image types, 64 KB otherwise). Any request with a body over 1 MB gets this, GET requests included.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 422

`invalid_params`: `params` or `metadata` do not match the schema; `errors` lists each problem.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |
| `errors`  required  | `array of FieldError` |  One entry per problem, sorted by `pointer`. At most 50 entries; when there are more, `detail` ends with "and N more errors".  max items 50  |
| `errors.[item]`  optional  | `object` |  |
| `errors.[item].message`  required  | `string` |  |
| `errors.[item].pointer`  required  | `string` |  JSON Pointer (RFC 6901) to the offending value, from the root of the request body: `/params/website_key`, `/params/proxy/port`, `/params` for the parameters object itself, `/metadata/order`, `/metadata` for the metadata object itself.  |
| `errors.[item].reason`  optional  | `enum` |  Machine-readable kind, present for image problems: `image_too_large` (over 1,000,000 characters, the pixel or frame limits, or the images of the task together over the per-task limit; the pointer is the image that went over), `image_empty`, `image_base64` (not valid base64), `image_format` (not a PNG, JPEG, GIF, WebP or BMP image, a multi-picture JPEG, or malformed or truncated). New values may be added.  one of "image\_too\_large", "image\_empty", "image\_base64", "image\_format"  |

### 429

`rate_limited`: too many tasks created per second by this key, the same task polled too often, the sandbox's per-organization rate, usage queried too often, the catalog fetched too often from this IP, or this IP sent too many invalid keys. `concurrency_limited`: the organization has too many tasks in flight for this captcha family (or, with a test key, too many sandbox tasks still processing). Wait `Retry-After` seconds.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional), `Retry-After`.

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 500

`internal`: an error on our side.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional).

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

### 503

`service_unavailable`: no capacity right now (all solvers busy or failing, the gateway is overloaded, a dependency is unavailable). For `POST /v1/tasks` nothing was created or charged. Wait `Retry-After`.

Headers: `Noptcha-Request-Id`, `RateLimit` (optional), `RateLimit-Policy` (optional), `Retry-After`.

Content: `application/problem+json`

| Field | Type | Description |
| --- | --- | --- |
| `code`  required  | `string` |  Machine-readable error code (see the table).  |
| `detail`  optional  | `string` |  Human-readable explanation of this occurrence.  |
| `request_id`  required  | `string` |  Same as the `Noptcha-Request-Id` header.  |
| `status`  required  | `integer` |  The HTTP status code.  |
| `title`  required  | `string` |  |
| `type`  required  | `string` |  format: uri  |

Header descriptions and every schema: [Schemas](https://noptcha.com/docs/api-reference/schemas.md). Machine-readable: [openapi.json](https://noptcha.com/openapi.json), [openapi.yaml](https://noptcha.com/openapi.yaml).
