{/* Metadata lives in ./layout.tsx */}

# Ingest status

See what the API accepted, rejected, and superseded, and how complete your cost data is. {{ className: 'lead' }}

<Warning>
  Not live yet. Wire contract below is the intended v1 surface.
</Warning>

---

## `GET /v1/ingest/status`

**Scope:** `read`. Works with publishable or secret keys that carry `read`.

Returns per-kind counters over rolling windows (24h / 7d / 30d):

| Field | Meaning |
| --- | --- |
| `accepted` / `rejected` / `superseded` | Outcomes from the ingest log |
| `last_received_at` | Most recent accepted push |
| `top_error_codes` | Frequent rejection codes with sample messages |
| `coverage` | COGS complete %, gateway-fee actuals %, tax present % |

Use this endpoint in CI after a backfill: zero unexplained rejections is the bar before treating a dataset as complete.

### Polling

The response is computed at most once per 10 seconds per shop, no matter how many clients ask, so polling faster only returns the same answer. Every response carries an `ETag`; send it back as `If-None-Match` and an unchanged status costs a `304` with no body. Poll every 10 seconds while watching a backfill, and back off when idle.

If the underlying store is unreachable, the endpoint returns `503` with `Retry-After` instead of pretending the counters are zero. Treat `503` as "status unknown", never as "nothing ingested".

### Related

- `GET /v1/source`: registered platform, currency, timezone, connection status
- Connect page in the app (status, coverage, per-source daily counts, key management)
