> ## 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.

# Changelog

> API and documentation updates — including any breaking change shipped during early access, each with a migration note.

While the v1 API is in [early access](/conventions/versioning), breaking changes may occasionally ship in place. Every one is recorded here with what changed and how to migrate.

<Update label="July 2026">
  ## Transfer a unit between owners

  A unit can now move from its current owner to a new owner — tap-authorized like a claim, but executed by the current owner:

  * `POST /v1/units/{unit_id}/transfers` (session token required) creates the transfer and returns a `transaction` payload. **Only the unit's current owner can submit it** — Endstate authorizes the transfer but never relays it, and the authorization is valid for 30 minutes.
  * `GET /v1/units/{unit_id}/transfers/{transfer_id}` (API key or session token) polls status: `prepared` → `confirmed`; `expired` and `failed` are terminal.
  * New error codes: `transfer.in_progress`, `transfer.already_to_recipient`, `transfer.owner_unknown`, `transfer.not_found`.

  See the new [Transfers](/concepts/transfers) concept page.

  ## Replace a unit's chip

  Until a unit is claimed, its chip can now be replaced — for example when a chip is damaged or fails QA after pairing but before the item reaches its owner:

  * `POST /v1/units/{unit_id}/chip-replacements` pairs an existing, unpaired chip to the unit and retires the current one. Endstate performs the swap; replacement is asynchronous.
  * `GET /v1/units/{unit_id}/chip-replacements/{replacement_id}` polls status (`prepared` → `submitted` → `confirmed`; `failed` is terminal).
  * New error codes: `chip_replacement.locked` (unit already claimed — the chip is permanently locked), `chip_replacement.in_progress`, and `chip_replacement.not_found`.

  See [Replacing a chip](/concepts/chips#replacing-a-chip).

  ## `chain_id` is now optional on collection create

  Collections are created on your organization's **default network** when `chain_id` is omitted — configured by Endstate at onboarding, so most integrations never need to send a network identifier. An explicit `chain_id` is still accepted as an override, but must be one of the networks enabled for your organization.

  `GET /v1/settings` now returns your network configuration alongside `default_redirect_url`: `default_chain_id` (the default network, or `null` if none is configured) and `allowed_chain_ids` (the networks an explicit `chain_id` may use). Both are read-only.

  No migration needed — requests that send `chain_id` keep working unchanged.

  ## Single-resource responses are now top-level (breaking)

  `POST`, `GET`, and `PATCH` responses for collections and units previously wrapped the resource in an envelope — `{ "collection": {...} }` / `{ "unit": {...} }`. They now return the resource's fields at the **top level**, making every single-resource response uniform (chips, verify, session tokens, claims, and settings were already top-level).

  **Migration:** if your integration reads `response.collection.id` or `response.unit.id` from these endpoints, read the same fields at the top level instead (`response.id`, `response.collection.token`, ...). List responses are unchanged — they still wrap under a plural key alongside `pagination`. See [Response shape](/conventions/responses).

  ## Empty request bodies accepted on all-optional POSTs

  A `POST` with a JSON content-type and an empty body previously failed JSON parsing. An empty or whitespace-only body is now treated as `{}`, so requests like `POST /v1/chips/{chip_id}/tap` work without a body. Endpoints with required body fields still validate as before.
</Update>

<Update label="June 2026">
  ## Tap redirects

  Control where a user lands after tapping a chip, at three levels — the most specific one wins:

  * `redirect_url` is a new (nullable, always-present) field on the unit and collection resources, accepted on create and editable via new `PATCH /v1/units/{unit_id}` and `PATCH /v1/collections/{collection_id}` endpoints.
  * New `GET`/`PATCH /v1/settings` endpoints manage the org-wide `default_redirect_url`.
  * Redirected taps carry `endstate_chip_id` and `endstate_e` query parameters so your page can verify the tap.

  See [Tap redirects](/concepts/tap-redirects).

  ## Claims

  Transfer on-chain ownership of a unit to a recipient wallet, authorized by the session token from a recent tap of that unit's chip:

  * `POST /v1/units/{unit_id}/claims` creates a claim (`endstate_relay` or `client_broadcast` execution).
  * `GET /v1/units/{unit_id}/claims/{claim_id}` polls status (`claiming` → `claimed` / `expired` / `failed`).

  See [Claims](/concepts/claims) and the [Claim a unit](/guides/claim-a-unit) guide.
</Update>
