> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usenexio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Completeness and errors

> Tell a complete answer from a partial, unavailable or refused one, know when data was read, and retry and cache safely.

An empty list can mean "there are none", "you may not see them", "the source never supplied them" or "the warehouse did not answer". Records gives each of those a different signal. Every read, and every family inside a composite read, ends in one of the outcomes below, and each outcome has its own signal on the wire. This page is the one place those outcomes are defined; other pages link here.

## The outcome state model

| Outcome                        | How it appears on the wire                                                                                                                                                                                                             | What it means                                                                       | What to do                                                                                  |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Complete**                   | 200. `page.next_cursor` is `null`. A family's `presence` is `present`; a composite family's `coverage` is `complete`.                                                                                                                  | Every row in scope was read. An empty `data` array here is a true zero.             | Render it, including "none".                                                                |
| **Bounded page**               | 200. `page.next_cursor` is a string.                                                                                                                                                                                                   | This page is complete; more rows follow.                                            | Fetch the next page ([Registers and pagination](/data-services/registers)).                 |
| **Partial**                    | 200. A composite family has `coverage: "partial"` with a `reason` (for example `page_limit`), or a register carries a `note`.                                                                                                          | Part of the answer was read; the rest was cut by a bound or could not be completed. | Render what you have and say it is partial. Read the family's own route for the rest.       |
| **Unavailable, with a reason** | A composite family has `presence: "unknown"`, `coverage: "unavailable"` and a `reason`. For a whole route: 409 `book_unavailable` with `details.reason`, or 503 `book_unavailable` with reason `busy`.                                 | This read could not be served now. It says nothing about whether rows exist.        | Show "unavailable", never "none". Retry per the table below.                                |
| **Never supplied**             | A family has `presence: "absent"`.                                                                                                                                                                                                     | The connected source does not supply this dataset at all.                           | Show that the source has no such data. Retrying will not change it.                         |
| **Refused by design**          | 200 with `notice {code, message}` on the family (for example `org_scoped_only`), or a field blanked because its field class is withheld (`null`, or `0`, `""` or `false` on a field that is not nullable), or a 403 authority refusal. | The person may not see this.                                                        | Show that access is limited. See [Authority and scope](/data-services/scope#refusal-codes). |

One rule sits under all of these: a bound that cuts rows is reported. A composite family reports it as partial coverage with a reason, and a read whose statement has a declared row ceiling fails as a whole when the rows exceed it (409 `book_unavailable`, reason `result_too_large`).

## Per-family coverage

A composite read (a dedicated read that composes many families in one call; see [Composite reads and dedicated routes](/data-services/families#composite-reads-and-dedicated-routes)) reports each family in `families`:

| Field         | Values                                                  |
| ------------- | ------------------------------------------------------- |
| `presence`    | `present`, `absent`, `unknown`                          |
| `coverage`    | `complete`, `partial`, `unavailable`                    |
| `reason`      | Why the coverage is not complete (below)                |
| `duration_ms` | How long the family read took                           |
| `row_count`   | Rows read. Sent by some families, and only when nonzero |

| Reason                                                                | Coverage    | Meaning                                                                     |
| --------------------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- |
| `page_limit`                                                          | partial     | The family has more rows than one composite page holds. Read its own route. |
| `query_first_partial`, `row_cap`                                      | partial     | A sub-read hit its bound.                                                   |
| `family_read_timeout`                                                 | unavailable | The family missed its time budget on this read. Retry the read.             |
| `statement_busy`                                                      | unavailable | The warehouse queue was full. Retry.                                        |
| `family_read_unavailable`, `query_first_not_served`                   | unavailable | The family could not be read now.                                           |
| `scope_surface_denied`, `scope_dataset_denied`, `scope_action_denied` | unavailable | The person's policy does not grant this family. Not retryable.              |
| `org_scoped_only` or another notice code                              | unavailable | Refused by design for this scope.                                           |
| `source_families_incomplete`                                          | partial     | A summary family could not use every family it is built from.               |
| `source_families_unavailable`                                         | unavailable | A summary family could use none of the families it is built from.           |
| a named gap                                                           | unavailable | The source is missing something this family needs; the gap names it.        |

## When the data was read: the serving block

Every read of connected data (family reads, registers, and the keyed and composite reads) is a current read: Nexio queries your warehouse live, at request time, and does not hold the read to a fixed warehouse instant. Notes, workflow states and the action list are the exception: they are read from Nexio's own action ledger (see [Writes and the action ledger](/data-services/writes)), not from the warehouse. The task register merges tasks from the action ledger with follow-ups read from the warehouse. The owner directory (`GET /records/owners`) is also an exception: it is held in server memory for up to 15 minutes per seat and scope. So is risk evidence (`GET /records/accounts/{clientKey}/risk-evidence`): a repeat read within 10 minutes can answer from the evidence already assembled, with that assembly's original `serving` times. Document content (`GET /records/documents/{relationKey}/content`) is fetched from the system of record directly and returns the file's own bytes with no envelope. Every JSON read under `/api/v1/records` carries a `serving` block that says which connection answered and when the read ran, except the responses in [Which responses carry each block](#which-responses-carry-each-block). It looks like this:

```json theme={null}
"serving": {
  "binding_id": "2c4e6a8b-0d1f-4a3c-9e5b-7d9f1a3c5e7b",
  "overlay_rev": 0,
  "as_of": "2026-09-23T14:12:30Z",
  "source": {
    "mode": "query_first",
    "current": true,
    "fetched_at": "2026-09-23T14:12:30Z"
  }
}
```

| Field                                    | Meaning                                                                                                                                                                                                |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `binding_id`                             | The connection the read was served from.                                                                                                                                                               |
| `as_of`                                  | The request's read time. The action, note, task, workflow-state and edit-intent routes send the zero time `0001-01-01T00:00:00Z`, even when their account or policy scope check queries the warehouse. |
| `read_pin`                               | Not sent on Records reads, because no read is held to a fixed warehouse instant. `GET /records/status` sends it as `null`.                                                                             |
| `source.mode`                            | `query_first`: read live from the warehouse. The only mode served today.                                                                                                                               |
| `source.current`                         | `true`: the read queried the warehouse's current data at request time.                                                                                                                                 |
| `source.freshness`, `source.stale_since` | Not sent on Records reads.                                                                                                                                                                             |
| `source.fetched_at`                      | The request's read time, the same instant as `as_of`.                                                                                                                                                  |
| `overlay_rev`                            | Always `0` today.                                                                                                                                                                                      |
| `lens`                                   | Present on a lensed read: the target, their display name and the scope served.                                                                                                                         |

What a current read gives you:

* **One statement is consistent.** Where a response's rows and numbers come from one warehouse statement, they describe the same data. [Page, totals and facets](/data-services/registers#page-totals-and-facets) says which registers compute everything in one statement.
* **Separate statements are not a snapshot.** A response built from several statements (a composite read, or a register whose page and numbers come from separate statements) runs each of them separately against current data. A source change between them can make them disagree.
* **Every request reads again**, except the owner directory and risk evidence reads above. Two reads seconds apart can differ, and each page of a register walk is a new read. [When the data changes during a walk](/data-services/registers#when-the-data-changes-during-a-walk) says what that means for paging.
* **Date measures use the read's date.** In force, days to expiration and similar measures are computed against the date of the request's read time.
* **A failed read is refused.** When the warehouse cannot answer, the read answers 409 `book_unavailable` with a reason from the table below, or 503 `book_unavailable` when the statement queue is busy.

### Which responses carry each block

Every JSON read under `/api/v1/records` carries both a `serving` block and a [`scope` block](/data-services/scope#the-scope-block), except these responses:

| Response                                                                                          | `serving`                                                                                                          | `scope`                                                                                   |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
| `GET /records/actions`                                                                            | Yes                                                                                                                | No                                                                                        |
| `GET /records/owners`                                                                             | No                                                                                                                 | Yes                                                                                       |
| `GET /records/status`                                                                             | `null` until a connection exists                                                                                   | Its own, fuller block ([Preflight with the status read](#preflight-with-the-status-read)) |
| `POST /records/actions`                                                                           | Only when a command addressed an account or a policy; a batch whose commands all address catalog entities has none | Yes                                                                                       |
| The `/records/analyses` routes                                                                    | No                                                                                                                 | No                                                                                        |
| `GET /records/documents/{relationKey}/content`                                                    | No: the body is the file itself, not JSON                                                                          | No                                                                                        |
| `POST /records/accounts/{clientKey}/risk-runs`, `POST /records/accounts/{clientKey}/program-runs` | No: the body is a run reference                                                                                    | No                                                                                        |

## Response headers

| Header                 | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Server-Timing`        | On the `GET` reads that need `records:read` (not on the action ledger reads or on access and graph routes): the serving resolution (`pin`) when it ran on this request, each warehouse statement by name (with time to first result), composition when it ran, and the total. For example `pin;dur=3.2, account_register;dur=812.4;desc="query to first result 640 ms", compose;dur=4.1, total;dur=829.9`.                                                       |
| `X-Nexio-Engine-Build` | The engine commit that computed the response, when the running build is stamped with one. Sent on responses a route under `/api/v1/records` produces, reads and actions, refusals included. A response the platform answers before the route runs, such as a 401 or a 429, does not carry it, and neither does a `504 request_timeout` or `500 internal_error` written when the request times out or fails unexpectedly. Access and graph routes do not send it. |
| `Retry-After`          | On 503 `book_unavailable` (busy) and on 429 `rate_limited`: seconds to wait.                                                                                                                                                                                                                                                                                                                                                                                     |

## Caching and invalidation

There is no push invalidation for Records reads. Nothing notifies you when source data changes. Re-read when you need current data.

If you cache, key the entry on everything that shapes the answer: the credential, the acting principal and scope, the route and its parameters, and `X-Nexio-Engine-Build`. Store `serving.as_of` with the entry so you know when it was read. A new engine build can compute the same read differently, so a build change invalidates the entry.

## Preflight with the status read

`GET /api/v1/records/status` tells an application, before its first read, whether a connection is available and how the person resolves. It is the one read that answers an identity or scope refusal as data: when a qualifying connection exists, a person who cannot be served gets 200 with `scope.refused` set (`identity_unmapped`, `identity_needs_review`, `identity_suspended`, `identity_stale` or `scope_unavailable`), not a 403. Assertion and lens refusals still answer with their HTTP status. With no qualifying connection, the read admits the caller as other governed routes do, so an identity refusal answers with its HTTP status: for example, a request with neither an acting principal nor a registered service identity gets 403 `identity_unmapped`.

* `has_published: false` means no qualifying connection exists yet. Every other read would answer 409 `book_unavailable`.
* `scope` is the person's resolved scope: kind, selection, owner code count, and home office. `home_status` is `ok`, `none` or `unavailable`.
* `reads.account_register.state` is `available` (an `All` or `Platform` scope) or `scope_unsupported` (a `Self` scope). This block is advisory. The [account register](/data-services/registers) does not check it, so a `Self` person marked `scope_unsupported` here still reads the register. `code` is `null` when the state is `available`; for `scope_unsupported` it is `register_scope_unavailable`, a refusal the register route does not return today.
* `reads.producer_licensure.state` is `available`, `not_derived` or `version_mismatch`. `code` is `null` when the state is `available` and a refusal code otherwise.
* `read_modes` lists each read surface and how it is served.
* `entitlement` is present when the organization's posture is `shadow` or `lit` for this person.
* `include_team=true` adds the person's team to `entitlement.team`. `include_related_books` defaults to true. Any value other than a boolean answers 400 `invalid_request`.
* It accepts the `X-Nexio-Consumer`, `X-Nexio-Consumer-Build` and `X-Nexio-Consumer-Vocabulary` headers as diagnostics. They do not affect authorization.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.usenexio.com/api/v1/records/status \
    -H "Authorization: Bearer $NEXIO_API_KEY" \
    -H "X-Nexio-Acting-Principal: user_01J8Z3K4M5N6P7Q8R9S0T1U2V3" \
    -H "X-Nexio-Acting-Email: dana.ortiz@harborgroup.example"
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.get(
      "https://api.usenexio.com/api/v1/records/status",
      headers={
          "Authorization": "Bearer " + os.environ["NEXIO_API_KEY"],
          "X-Nexio-Acting-Principal": "user_01J8Z3K4M5N6P7Q8R9S0T1U2V3",
          "X-Nexio-Acting-Email": "dana.ortiz@harborgroup.example",
      },
      timeout=30,
  )
  response.raise_for_status()
  status = response.json()
  if not status["has_published"]:
      print("No connection is available yet")
  elif status["scope"].get("refused"):
      print("Cannot serve this person:", status["scope"]["refused"])
  else:
      print("Ready:", status["scope"]["kind"], status["scope"]["selection"])
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://api.usenexio.com/api/v1/records/status", {
    headers: {
      Authorization: `Bearer ${process.env.NEXIO_API_KEY}`,
      "X-Nexio-Acting-Principal": "user_01J8Z3K4M5N6P7Q8R9S0T1U2V3",
      "X-Nexio-Acting-Email": "dana.ortiz@harborgroup.example",
    },
  });
  if (!response.ok) throw new Error(`status read failed: ${response.status}`);
  const status = await response.json();
  if (!status.has_published) console.log("No connection is available yet");
  else if (status.scope.refused) console.log("Cannot serve this person:", status.scope.refused);
  else console.log("Ready:", status.scope.kind, status.scope.selection);
  ```
</CodeGroup>

```json 200 OK theme={null}
{
  "has_published": true,
  "status": null,
  "serving": {
    "binding_id": "5f0c9a52-1d2b-4c47-9a0e-3b8d6f1e2a47",
    "overlay_rev": 0,
    "as_of": "2026-09-23T14:10:04Z",
    "read_pin": null,
    "source": {
      "mode": "query_first",
      "current": true,
      "fetched_at": "2026-09-23T14:10:04Z"
    }
  },
  "duration_ms": 318,
  "read_modes": {
    "account_register": "query_first",
    "policy_register": "query_first",
    "renewal_register": "query_first",
    "retention_renewals": "query_first",
    "activity_register": "query_first",
    "new_business_register": "query_first",
    "opportunity_register": "query_first",
    "placement_history": "query_first",
    "account_detail": "query_first",
    "book_actions": "query_first",
    "status": "query_first",
    "policies": "query_first",
    "claims": "query_first",
    "billing": "query_first",
    "contacts": "query_first",
    "documents": "query_first",
    "rollups": "query_first",
    "facets": "query_first",
    "expirations": "query_first",
    "renewals": "query_first",
    "employees": "query_first",
    "org_evidence": "query_first",
    "crm": "query_first",
    "generic_family": "query_first",
    "policy_coverages": "query_first",
    "policy_forms": "query_first",
    "policy_transactions": "query_first",
    "policy_exposures": "query_first",
    "policy_named_insureds": "query_first",
    "policy_parties": "query_first",
    "policy_history": "query_first",
    "policy_applicant": "query_first",
    "policy_commission": "query_first",
    "policy_personnel": "query_first",
    "claim_payments": "query_first",
    "claim_risk_items": "query_first",
    "claim_loss_history": "query_first",
    "claim_drivers": "query_first",
    "claim_contacts": "query_first",
    "claim_injured": "query_first",
    "claim_property_damage": "query_first",
    "claim_remarks": "query_first",
    "program_evidence": "query_first",
    "risk_evidence": "query_first",
    "class_knowledge": "query_first",
    "loss_summary": "query_first",
    "activity": "query_first",
    "certificates": "query_first",
    "submissions": "query_first",
    "vocabulary": "query_first"
  },
  "scope": {
    "kind": "Self",
    "principal": "user_01J8Z3K4M5N6P7Q8R9S0T1U2V3",
    "producer_code_count": 1,
    "selection": "boundary",
    "selection_source": "none",
    "home_market": "West Region",
    "home_office": "DEN",
    "home_office_label": "Denver",
    "home_status": "ok"
  },
  "reads": {
    "account_register": { "state": "scope_unsupported", "code": "register_scope_unavailable" },
    "producer_licensure": { "state": "not_derived", "code": "licensure_not_derived" }
  },
  "derived": {
    "risk_profile": { "found": false, "behind_head": false },
    "org_evidence": { "found": false, "behind_head": false },
    "org_retention": { "found": false, "behind_head": false }
  }
}
```

`status` is always `null` today. `entitlement` is omitted in this example because the organization's posture is `dark`.

## book\_unavailable reasons and retry guidance

`book_unavailable` means the read could not be served now. It is not a server fault and it is not an empty answer.

| Status | `details.reason`            | Cause                                                                                                                                        | Retry                                                         |
| ------ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| 409    | none                        | No qualifying connection exists for the organization. A `connection_id` that names no qualifying connection answers 404 `not_found` instead. | No. Check `/records/status`; Nexio configures the connection. |
| 409    | `executor_timeout`          | The warehouse did not answer within the statement timeout.                                                                                   | Yes, after a short wait. Narrow the request if it repeats.    |
| 409    | `budget_exhausted`          | The read used up its warehouse statement budget.                                                                                             | Yes, after a short wait.                                      |
| 409    | `scope_datasources_missing` | A whole-organization scope has no bound source datasources on this connection, so the read is refused rather than served unbounded.          | No. Nexio fixes the connection binding.                       |
| 409    | `warehouse_unavailable`     | The warehouse or a source table could not be read.                                                                                           | Yes, with backoff.                                            |
| 409    | `result_too_large`          | The read matched more rows than its ceiling.                                                                                                 | No. Narrow the filters.                                       |
| 503    | `busy`                      | The warehouse statement queue for this connection is full.                                                                                   | Yes, after `Retry-After` seconds.                             |

Other status codes on Records reads:

| Status | Code                                   | Retry                                                                                                                                                                                                                                 |
| ------ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 429    | `rate_limited`                         | After `Retry-After`. Requests under `/api/v1/records` share a per-organization budget of at least 30,000 requests per minute.                                                                                                         |
| 499    | `client_closed_request`                | The client closed the connection; nobody read the answer.                                                                                                                                                                             |
| 503    | `resolve_retry_exhausted`              | Yes. Authority resolution kept conflicting with a concurrent change.                                                                                                                                                                  |
| 504    | `request_timeout`                      | Yes, narrowed. The route timeout is 30 seconds, except 180 seconds for program evidence and, by default, 20 seconds for the composite read `/accounts/{clientKey}/picture` and its `named-insureds` and `policy-forms` sub-resources. |
| 500    | `internal_error`, `book_key_ambiguous` | Report it. `book_key_ambiguous` means a key matched more than one record.                                                                                                                                                             |

Cursor and filter errors are on [Registers and pagination](/data-services/registers#cursor-and-paging-errors). Authority refusals are on [Authority and scope](/data-services/scope#refusal-codes).

## Next

<CardGroup cols={2}>
  <Card title="Get status" href="/api-reference/data-services/get-status">Endpoint reference.</Card>
  <Card title="Errors" href="/reference/errors">Every error code on the platform.</Card>
</CardGroup>
