---
title: Jobs, Polling, and Webhooks
description: Job lifecycle, polling, and webhook delivery for completed analysis.
type: doc
icon: webhook
sidebar:
  label: Jobs, Polling, and Webhooks
  order: 5
  icon: webhook
search:
  tags: [api]
---
Analyze returns a **job** immediately. The result arrives later. Endpoints: [Jobs API](/reference/jobs), [Account API](/reference/account) (webhooks).

## Submit

Submit returns a job object right away, with `job_id`, `status: queued`, and `result: null`:

```json
{
  "job_id": "189bce4a-52cb-4e60-8586-cef89e719109",
  "status": "queued",
  "created_at": "2026-02-22T09:14:00Z",
  "completed_at": null,
  "result": null,
  "job_type": "model",
  "api_version": "v2",
  "model_name": "pulse"
}
```

`job_type` is `"model"` or `"sign"`. Both `model_name` and `sign_name` may be present; the unused discriminator is `null`. See [Response Schema](/reference/response-schema#job-response).

## Job statuses

`status` moves through `queued` and `running` to one of three terminal values.

| Status | Meaning |
|---|---|
| `queued` | Accepted and waiting to be processed. `result` is `null`. |
| `running` | Processing. `result` is `null`. |
| `done` | Analysis completed. `result` contains the full output. |
| `failed` | Processing ended without a result. `result` is usually `null`. |
| `timed-out` | Processing ended without a result. `result` is usually `null`. |

For a valid `job_id` on your account, `GET /v2/jobs/{job_id}` returns `200 OK` with the job object. `failed` and `timed-out` are expressed in `status` in the body, not only via HTTP error codes. Poll until `status` is `done`, `failed`, or `timed-out`, then branch. Full contract: [Response Schema — Job status: failed or timed-out](/reference/response-schema#job-status-failed).

When `status` is `done`, read `result`. Model jobs: `summary`, `signals[]`, `audio_quality`, `extended_metrics`. Sign jobs: `signal` plus `audio_quality`. Fields: [Response Schema](/reference/response-schema). How to act: [Interpreting Results](/guides/interpreting-results).

## Polling

Retrieve the job with `GET /v2/jobs/{job_id}`:

<CodeGroup param="lang">

```bash cURL
curl https://api.amplifierhealth.com/v2/jobs/189bce4a-52cb-4e60-8586-cef89e719109 \
  -H "X-Account-ID: your-account-id" \
  -H "X-API-Key: your-api-key"
```

```javascript JavaScript
const response = await fetch("https://api.amplifierhealth.com/v2/jobs/189bce4a-52cb-4e60-8586-cef89e719109", {
  headers: {
    "X-Account-ID": process.env.AMPLIFIER_ACCOUNT_ID,
    "X-API-Key": process.env.AMPLIFIER_API_KEY,
  },
});

const data = await response.json();
```

```python Python
# Requires httpx: pip install httpx
import os
import httpx

response = httpx.get(
  "https://api.amplifierhealth.com/v2/jobs/189bce4a-52cb-4e60-8586-cef89e719109",
  headers={
      "X-Account-ID": os.environ["AMPLIFIER_ACCOUNT_ID"],
      "X-API-Key": os.environ["AMPLIFIER_API_KEY"],
  },
)

data = response.json()
```

</CodeGroup>

Poll at 2–5 second intervals. Most jobs complete within a few seconds; longer recordings may take up to 30 seconds. Diarized and long recordings can take several minutes. This cadence fits within the [job status polling rate limit](/reference#rate-limits).

Parse timestamps with an ISO 8601-compatible library — the API may return timestamps with or without fractional seconds and with varying timezone designators. See [Response Schema — Timestamps](/reference/response-schema#timestamps).

## Webhooks

Webhooks POST the job object at a terminal status. Use when the submitter cannot poll, or as an audit trail. Still poll as fallback.

Register a webhook with `POST /v2/account/webhook`: `url` (URI, max 2083 characters; HTTPS in production) and `secret_key`. Per-job override: `webhook_url` + `webhook_secret_key` on analyze — send the secret whenever you send a URL. Shapes: [Account API](/reference/account).

### How webhooks work

- Webhooks are sent **asynchronously** when the job reaches a terminal status: `done`, `failed`, or `timed-out`. The body is the job object — check `status` before reading `result`. Polling is still useful as a fallback, including for jobs that never reach `done`.
- The API sends an HTTP POST to your configured URL with a JSON payload.
- If your endpoint is unavailable or returns a non-2xx status, the system retries delivery up to 5 times with increasing delays. Respond within 30 seconds to stay inside the delivery timeout.

### Webhook request format

Headers:

- `Content-Type: application/json`
- `X-Webhook-Signature` — HMAC-SHA256 signature of the raw request body; use it to verify the request came from Amplifier.

Payload: the completed job object. Check `status` before reading `result`. Fields: [Response Schema](/reference/response-schema).

### Signature verification

Verify every payload before processing it:

1. Read the raw request body (as bytes or string) and the `X-Webhook-Signature` header.
2. Compute HMAC-SHA256 of the raw body using your `secret_key`.
3. Compare the computed value with the header using a constant-time comparison.

Keep the `secret_key` on your server and use it only for signature verification.

### Handling retries

Because delivery is retried, the same `job_id` can arrive more than once. Implement an idempotency check on `job_id` so a repeated delivery is recognized and processed once.

## Choosing polling or webhooks

| Approach | Fits when |
|---|---|
| Polling `GET /v2/jobs/{job_id}` | The submitting process can wait for the result, or you already have a job queue that can re-check. |
| Webhooks | Submitter cannot poll (e.g. client upload, result to a backend), or you want an audit trail. |

Both can be used together: register a webhook and still poll as a fallback.

## Error handling

`401`: check `X-Account-ID` and `X-API-Key`. `429`: exponential backoff; read `Retry-After`. `500`: exponential backoff. Codes: [Errors](/reference/errors#retry-guidance).

`GET /v2/jobs/{job_id}` returns `404` for a missing or cross-account `job_id` — [Errors](/reference/errors#error-codes).

When `result.summary.recommended_action` is `inconclusive`, treat it as no clear signal; prefer re-recording — [Recommended action logic](/guides/interpreting-results#recommended-action-logic).
