# Synchronous and Asynchronous Endpoints

Write endpoints fall into two categories. The HTTP success status code tells you which is which.

## Synchronous (200 OK / 201 Created)

The response body contains the final state of the resource. No follow-up calls are required.

| Endpoint family | Success status | Returns |
|---|---|---|
| All read endpoints (`GET ...`) | `200` | Resource (or paginated list) |
| `POST /v1/programs`, `POST /v1/programs/{uuid}/entities`, `POST /v1/programs/{uuid}/monitors`, `POST /v1/entities/{uuid}/notes` | `201` | Created resource |
| `PATCH` / `DELETE` on any resource | `200` | Updated or soft-deleted resource |
| `POST /v1/entities/{uuid}/archive`, `POST /v1/entities/{uuid}/unarchive` | `200` | Updated entity |
| `POST /v1/entities/{uuid}/id-checks`, `POST /v1/adhoc-id-checks` | `200` | Completed ID check (full payload, including the final `outcome`) |

Identity verification checks are run synchronously against the upstream provider before the response is returned - the `outcome` (`pass`/`fail`) is final by the time you get the response. The one exception is an ID check completed through an IDPass verification, which reports `pending` until the person finishes (see [IDPass](/docs/guides/watcheye_api/idpass)); otherwise there is no `pending` state to poll for ID checks.

## Asynchronous (202 Accepted)

The response confirms that the work has been queued. The actual screening runs in the background and you must poll the corresponding show endpoint until `status` (or, for monitor runs, `process_status`) reaches a terminal value.

| Launch endpoint | Poll | Terminal values |
|---|---|---|
| `POST /v1/entities/{uuid}/checks` | `GET /v1/checks/{uuid}` | `status` is `complete` or `failed` |
| `POST /v1/adhoc-checks` | `GET /v1/adhoc-checks/{uuid}` | `status` is `complete` or `failed` |
| `POST /v1/monitors/{uuid}/run` | `GET /v1/monitors/{uuid}` | `process_status` is `null` (idle again), `failed` or `paused` |

The launch response carries the new resource's `uuid` (and on checks, a `detail_url` you can use directly). A reasonable polling cadence is every 2-5 seconds for the first 30 seconds, backing off to every 15-30 seconds for longer-running operations. Most screening checks complete within a few seconds; a monitor run across thousands of entities can take several minutes.

## Idempotency interacts with polling

When you retry an async launch endpoint with the same `Idempotency-Key`, the replayed `202` response carries the same `uuid` as the original call (and an additional `Idempotent-Replay: true` response header). The background work was already queued by the original call - keep polling the original `uuid` rather than launching a new one. See [Idempotency](/docs/guides/watcheye_api/idempotency) for the full contract.
