> ## Documentation Index
> Fetch the complete documentation index at: https://docs.awaithumans.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# GET /api/tasks/{id}/poll

> Long-poll a task until it reaches a terminal status.

```http theme={"system"}
GET /api/tasks/{id}/poll?timeout=25
Authorization: Bearer <ADMIN_API_TOKEN>
```

Holds the connection open for up to `timeout` seconds (default 25, max 30). Returns immediately when the task transitions to a terminal status. If still pending after the timeout, returns the current status and the client reconnects.

## Why long-polling

Plain `GET /api/tasks/{id}` works for one-shot reads, but agents waiting on tasks need either polling (every second → DB load + latency) or long-polling (one connection, server pushes when state changes). awaithumans uses long-polling because:

* One connection per task, parked at the server
* Server-side detection of terminal transitions (no polling cost)
* Any HTTP client works (no WebSockets / SSE complexity)

The SDK reconnects every \~25 seconds, well under typical gateway timeouts (60s).

## Query params

| Param     | Type | Default | Description                                |
| --------- | ---- | ------- | ------------------------------------------ |
| `timeout` | int  | 25      | Max seconds to hold the connection (1–30). |

## Response

```http theme={"system"}
HTTP/1.1 200 OK
Content-Type: application/json
```

```json theme={"system"}
{
  "status": "completed",
  "response": { "approved": true, "notes": "Duplicate charge confirmed." },
  "completed_at": "2026-05-12T08:05:23.456Z",
  "timed_out_at": null
}
```

| Field          | Type              | Description                                                                                                                                                    |
| -------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`       | string            | One of `created`, `notified`, `assigned`, `in_progress`, `submitted`, `verified`, `rejected`, `completed`, `timed_out`, `cancelled`, `verification_exhausted`. |
| `response`     | object \| null    | Set when status is `completed`. The validated response per `response_schema`.                                                                                  |
| `completed_at` | timestamp \| null | Set on `completed`.                                                                                                                                            |
| `timed_out_at` | timestamp \| null | Set on `timed_out`.                                                                                                                                            |

## Statuses your client cares about

| Status                   | Meaning                                   | Client action                       |
| ------------------------ | ----------------------------------------- | ----------------------------------- |
| `completed`              | Human submitted, verifier (if any) passed | Use `response`; you're done.        |
| `timed_out`              | Scheduler hit `timeout_at`                | Raise `TaskTimeoutError`.           |
| `cancelled`              | Agent or operator cancelled               | Raise `TaskCancelledError`.         |
| `verification_exhausted` | Verifier rejected `max_attempts` times    | Raise `VerificationExhaustedError`. |
| (anything else)          | Still pending                             | Reconnect after the response; loop. |

## Errors

| Status | `error_code`     | Cause                                     |
| ------ | ---------------- | ----------------------------------------- |
| 401    | —                | Missing or wrong auth.                    |
| 403    | —                | Caller isn't operator / admin / assignee. |
| 404    | `TASK_NOT_FOUND` | Task ID doesn't exist.                    |

## Polling vs webhooks

For agents that block on `await_human()` long enough that polling cost matters, use the [Temporal](/adapters/temporal) or LangGraph adapters — they replace polling with workflow signals via the `callback_url` mechanism.

For everything else (Flask handlers, scripts, simple async loops), polling is fine. The cost: one HTTP connection per pending task, held for \~25s at a time.

## SDK equivalent

```python theme={"system"}
# Python — happens automatically inside await_human()
from awaithumans import await_human_sync
decision = await_human_sync(...)   # internal polling loop
```

```ts theme={"system"}
// TypeScript
import { awaitHuman } from "awaithumans";
const decision = await awaitHuman({ ... });   // internal polling loop
```
