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

# Response shape

> How successful responses are structured. Single resources are returned at the top level; list responses wrap their array under a plural key alongside pagination.

## Single resources are top-level

Every single-resource response returns the resource's fields at the **top level** — there is no wrapper key. This applies uniformly to collections, units, chips, verify results, session-token introspection, claims, transfers, and chip replacements.

| Endpoint                                                    | Shape                                           | Read it as                  |
| ----------------------------------------------------------- | ----------------------------------------------- | --------------------------- |
| `POST /v1/collections`, `GET /v1/collections/{id}`, `PATCH` | **Top-level**: `{ id, contract, name, ... }`    | `response.id`               |
| `POST /v1/units`, `GET /v1/units/{id}`, `PATCH`             | **Top-level**: `{ id, collection, chips, ... }` | `response.collection.token` |
| `POST /v1/chips` (pair)                                     | **Top-level**: `{ chip_id, unit, ... }`         | `response.chip_id`          |
| `POST /v1/chips/{id}` (verify)                              | **Top-level**: `{ session_token, unit, ... }`   | `response.session_token`    |
| `GET /v1/session-tokens/current`                            | **Top-level**: `{ chip_id, unit_id, ... }`      | `response.unit_id`          |
| `POST /v1/units/{id}/claims`, `GET .../claims/{claim_id}`   | **Top-level**: `{ id, status, to, ... }`        | `response.status`           |
| `POST /v1/units/{id}/transfers`, `GET .../transfers/{id}`   | **Top-level**: `{ id, status, to, ... }`        | `response.status`           |

<Note>
  Earlier versions of this API wrapped single collection and unit responses in a
  `collection` / `unit` envelope (`{ "collection": {...} }`). That envelope is
  gone — if your integration reads `response.collection.id` from `GET
      /v1/collections/{id}` or `response.unit.id` from `GET /v1/units/{id}`, update
  it to read the fields at the top level.
</Note>

Some top-level responses contain a nested resource as a **field** — for example, the verify response includes the verified `unit`, and the chip-pair response includes a `unit` snapshot. That nesting is part of the resource's own shape, not an envelope.

For example, creating a collection and then polling it:

```ts theme={null}
const created = await fetch(`${ENDSTATE}/v1/collections`, {
  method: "POST",
  headers,
  body,
}).then((r) => r.json());
const collectionId = created.id;

const polled = await fetch(`${ENDSTATE}/v1/collections/${collectionId}`, {
  headers,
}).then((r) => r.json());
if (polled.contract.status === "active") {
  /* ready */
}
```

And verifying a tap:

```ts theme={null}
const verified = await fetch(`${ENDSTATE}/v1/chips/${chipId}`, {
  method: "POST",
  headers,
  body,
}).then((r) => r.json());
const token = verified.session_token.token; // the verified unit is verified.unit
```

## List responses

List endpoints wrap their array under a plural key alongside `pagination`:

```json theme={null}
{ "collections": [ ... ], "pagination": { "limit": 50, "has_more": false, "next_cursor": null } }
```

See [Pagination](/conventions/pagination) for cursoring through results.

## Errors

Errors use a separate, uniform envelope — `{ "error": { "code", "message", "request_id" } }` — across every endpoint. See [Errors](/conventions/errors).
