# Status codes

## Evidence statuses

On every object (`status`) and packet (`status`, with every non-verified status also listed in `flags`).

| Status | On an object | On a packet |
| --- | --- | --- |
| `VERIFIED` | Checked against its source | At least one verified proposition, no conflicts or temporal uncertainty |
| `UNVERIFIED_CANDIDATE` | Not yet checked against an official source | Every proposition is unverified |
| `INSUFFICIENT_EVIDENCE` | (not used) | No proposition in the dataset answers the question. Say so; do not fill the gap |
| `CONFLICTING_AUTHORITY` | Another record contradicts it | The packet contains a `conflicts_with` relationship; see `conflicts` |
| `TEMPORAL_UNCERTAINTY` | `as_of` falls in a date range flagged as uncertain | Some proposition is temporally uncertain on `as_of` |

A packet's status is the first of these that applies: `INSUFFICIENT_EVIDENCE`, `CONFLICTING_AUTHORITY`, `TEMPORAL_UNCERTAINTY`, `UNVERIFIED_CANDIDATE`, `VERIFIED`. A `VERIFIED` packet can still contain unverified cases; check `flags`.

## Packet limitations

| Code | When |
| --- | --- |
| `NOT_LEGAL_ADVICE` | Always |
| `DATASET_UPDATES` | Always. The packet names its dataset version and says the dataset is updated from time to time, so the same question can later return a different packet |
| `FACT_SPECIFIC_QUESTION` | The question reads as being about a particular situation ("should I sue", "my landlord") |
| `OUT_OF_SCOPE_TERMS` | The question mentions things this dataset doesn't cover (cars, snow removal procedure, and so on) |
| `UNKNOWN_TOPICS` | `topics` contained IDs that don't exist |
| `UNKNOWN_JURISDICTION` | The jurisdiction isn't covered |
| `NO_COVERAGE` | Nothing in the dataset matches the question |
| `DECIDED_AFTER_AS_OF` | A case in the packet was decided after `as_of` |
| `LIMITED_RULE` | A proposition in the packet is narrowed by another record |
| `CONFLICT_OUTSIDE_PACKET` | An object here conflicts with a record outside the packet's jurisdictions or date. The packet is not `CONFLICTING_AUTHORITY`, but the object's own `status` is; follow its relationships |
| `UNVERIFIED_ITEMS` | Some objects haven't been checked against an official source |
| `HUMAN_REVIEW_PENDING` | Some objects haven't been reviewed by a lawyer |
| `DATASET_COVERAGE` | Coverage is selective; see [coverage](https://agents.newyorkeverydaylawreference.com/docs/coverage) |

## Resolve statuses

`current`, `revised`, `superseded`, `hash_mismatch`, `version_not_found`, `not_found`. See [citation and portability](https://agents.newyorkeverydaylawreference.com/docs/citation#resolving).

## Errors

Errors are `application/problem+json`:

```json
{
  "type": "https://agents.newyorkeverydaylawreference.com/docs/statuses#invalid_request",
  "title": "Invalid request",
  "status": 400,
  "code": "INVALID_REQUEST",
  "detail": "q: Too small: expected string to have >=1 characters",
  "request_id": "req_…",
  "issues": [{ "path": "q", "message": "Too small: expected string to have >=1 characters" }]
}
```

Match on `code`, which is stable; `detail` wording may change.

<h3 id="invalid_request">INVALID_REQUEST (400)</h3>

The request didn't validate: missing or malformed parameters, a body that isn't JSON, more than 100 IDs in a batch, or a cursor from a different query. `issues` lists each problem with its path.

<h3 id="not_found">NOT_FOUND (404)</h3>

No object, packet, or route with that ID or path. Packets not in storage can be rebuilt by posting the same request again.

<h3 id="version_not_found">VERSION_NOT_FOUND (404)</h3>

The object exists, but not at that version. `detail` gives the current version.

<h3 id="not_acceptable">NOT_ACCEPTABLE (406)</h3>

The `Accept` header asked for a representation we don't offer. Available: `application/json`, `text/markdown`, `text/html`.

<h3 id="payment_required">PAYMENT_REQUIRED (402)</h3>

The request asked for an evidence packet without the access token from a paid checkout. The packet is not built. Send `Authorization: Bearer` with the token the checkout returned.

<h3 id="payload_too_large">PAYLOAD_TOO_LARGE (413)</h3>

POST bodies are limited to 64 KB.

<h3 id="rate_limited">RATE_LIMITED (429)</h3>

More than 600 requests in 60 seconds from the same client IP (configurable with `RATE_LIMIT_REQUESTS` and `RATE_LIMIT_WINDOW_SECONDS`). `Retry-After` and `X-RateLimit-*` headers say when to try again. `GET /health` does not count.

<h3 id="internal_error">INTERNAL_ERROR (500)</h3>

A bug on our side. Please report it with the `request_id`.
