# Read current source and pipeline health

`GET /api/v1/data/health` - [human page](https://aicdapi.com/api-reference#readCivicHealth)

**Release status.** Limited availability

Includes safe source checks, pending work and failures. Raw errors, connector configuration and archive credentials are excluded. A degraded response can still be HTTP200 and must be evaluated by the caller.

**Authentication.** Customer API key: `Authorization: Bearer aicd_...`. A browser session does not authenticate this endpoint. Required scope: `civic:read`.

### Example request

```bash
curl -X GET 'https://aicdapi.com/api/v1/data/health' \
  -H "Authorization: Bearer $AICD_API_KEY"
```

### Response 200

Source and pipeline health.

| Field | Type | Required | Bounds | Description |
| --- | --- | --- | --- | --- |
| `data` | object (CivicHealth) | yes |  |  |
| `data.status` | one of `healthy` \| `degraded` \| `unavailable` | yes |  |  |
| `data.checkedAt` | string (date-time) | yes | pattern ^(?:(?:\\d\\d[2468][048]\|\\d\\d[13579][26]\|\\d\\d0[48]\|[02468][048]00\|[13579][26]00)-02-29\|\\d{4}-(?:(?:0[13578]\|1[02])-(?:0[1-9]\|[12]\\d\|3[01])\|(?:0[469]\|11)-(?:0[1-9]\|[12]\\d\|30)\|(?:02)-(?:0[1-9]\|1\\d\|2[0-8])))T(?:(?:[01]\\d\|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z\|([+-](?:[01]\\d\|2[0-3]):[0-5]\\d)))$ |  |
| `data.sources` | object[] | yes |  |  |
| `data.pipeline` | object | yes |  |  |

### Errors

| Status | `error.code` | Description |
| --- | --- | --- |
| **400** |  | Invalid parameter, duplicate query field or malformed JSON. |
| **401** | `unauthorized` | Missing, invalid, expired or revoked credential. |
| **403** | `billing_channel_unset`, `billing_entitlement_required`, `forbidden` | Customer lacks the required grant. |
| **404** |  | Snapshot does not exist, belongs to another customer, or expired. |
| **410** |  | Cursor is older than the retained replay floor; start a new snapshot. |
| **413** | `response_too_large` | Request or response exceeds its size cap; reduce the page limit. |
| **429** | `rate_limited` | A per-account request, burst or export allowance was exhausted, or the account-wide abuse ceiling was reached. The abuse ceiling is account-wide, is not charged against the paid quota, and is charged after the identity lookup and before a revoked, expired, unpaid, or scope-denied rejection is decided. |
| **500** | `internal_error` | Unexpected operation failure; the response contains no private database details. |
| **503** | `authentication_unavailable` | Authentication, limit store or feed state is unavailable. |
| **504** | `timeout` | Database statement or request deadline exceeded. |

### Behaviour

- **Limits.** Counted against the per-account minute and burst allowances. A paid subscription uses its plan's own limits, which the public usage limits help lists and the account console shows. An account with no paid plan is limited by the stored account defaults, which the account console also shows. A separate account-wide abuse limit also applies to recognized subscription keys, counted separately for usable keys and for revoked or expired ones, so a compromised key you rotate does not reduce the new key's capacity. It is charged before a denial is decided and is not charged against your paid quota.
- **Retry-After.** Sent on 429 only, as whole seconds.
- **Caching.** Customer responses must not be cached.
