Conventions

Global conventions that apply to every Well API operation: JSON:API envelope, pagination, idempotency, versioning, and graph depth.

These conventions apply to every /v1 operation and are documented once here rather than repeated per endpoint.

JSON:API envelope

Request and response bodies follow a JSON:API-style envelope: a data object with type, id (responses), attributes, and relationships.

// request (create)
{ "data": { "type": "tasks", "attributes": { "title": "Chase invoice" } } }

// response
{
  "data": {
    "type": "tasks",
    "id": "7b2f…",
    "attributes": { "title": "Chase invoice", "status": "open", "created_at": "2026-06-07T10:00:00Z" },
    "relationships": { "assigned_to": { "data": { "type": "people", "id": "p_1" } } }
  }
}
  • Relationships are { "data": { "type", "id" } } (to-one) or { "data": [ … ] } (to-many).
  • Related resources may be sideloaded under a top-level included array (e.g. assignees on a task list).
  • Timestamps are ISO-8601 UTC. Soft-deletable resources carry deleted_at (null when live).

Pagination

List endpoints are cursor-paginated (keyset, not offset) — the same model the records pipeline uses.

ParamInMeaning
limitqueryPage size (default 20, max 500).
cursorqueryOpaque keyset token. Omit for page 1; pass the previous response's links.next.

Response carries the next cursor in links.next (and counts in meta):

{
  "data": [  ],
  "meta": { "total": 1280, "count": 20 },
  "links": { "next": "eyJpZCI6MTAwfQ==" }
}

links.next is null on the last page. Cursors are opaque — do not construct or parse them.

Some early resource pages document a JSON:API bracket form (page[limit] / page[cursor]). The canonical contract is the flat limit / cursor query params above; new endpoints use it uniformly.

Versioning

The surface is versioned in the path: /v1. Changes to /v1 are additive and backward-compatible; breaking changes ship under a new version path, never as a silent mutation of /v1.

Idempotency

Writes that are naturally non-idempotent (e.g. create) may accept an idempotency key where supported; replays within the window return the original result rather than creating a duplicate. Where an endpoint does not document idempotency, treat retries as potentially creating duplicates and guard on the client.

Graph depth (reads)

Read endpoints expose the related graph up to a bounded depth.

  • Default depth=1 (the entity + its direct relations, ≈150–200 fields). Selecting every field three hops out explodes to thousands of columns on graph-rich roots (transactions ≈6.7k, accounts ≈8.4k, payment_means ≈9.5k fields at depth 3) — beyond a single SQL statement.
  • Callers opt into depth=2/3 on smaller-graph roots; a breadth cap bounds field selection regardless.
  • Nested to-many collections are capped (e.g. 50 rows) at every level, not deeply paginated inline. meta.nested_cap and meta.capped_relations tell you which nested lists were truncated; page the full collection via its own GET /v1/<relation> resource endpoint.