# JSON:API documents and media types

> Read and write Hodoflow's path-versioned JSON:API documents with the correct envelopes, headers, resource identities, and relationships.

The JSON:API transport at `/api/json/v1` covers configuration and
observability. It follows JSON:API 1.0 document conventions and exposes only
reviewed resource actions and public fields. Warehouse fact rows belong to
[GraphQL](/graphql), and inbound deliveries belong to
[webhook ingestion](/webhook-ingestion).

## Request headers

Every JSON:API request sends:

```http
Accept: application/vnd.api+json
Authorization: Bearer <token>
```

Requests with a body also send:

```http
Content-Type: application/vnd.api+json
```

Safe methods require `api_read`; unsafe create and update operations require
`api_write`. The [API reference](/reference) displays the exact scope for each
operation. Unsafe requests should also carry a unique `Idempotency-Key` so a
retry cannot repeat a completed effect.

## Resource documents

A single-resource response has one `data` object:

```json
{
  "data": {
    "type": "workflow",
    "id": "00000000-0000-4000-8000-000000000001",
    "attributes": {
      "name": "Order intake",
      "is_active": true
    }
  },
  "jsonapi": { "version": "1.0" }
}
```

Treat the pair of `type` and `id` as the resource identity. Attributes are
resource-specific and may be nullable. Only fields shown in the reference are
public; internal secrets, hashes, raw payloads, share tokens, and unreviewed
actions remain unavailable.

A collection response has a `data` array. An empty array is a successful result,
not an error:

```json
{
  "data": [],
  "jsonapi": { "version": "1.0" },
  "links": {
    "self": "https://hodoflow.com/api/json/v1/workflows?page[limit]=10",
    "next": null,
    "prev": null
  }
}
```

Always pass an explicit limit when an operation accepts pagination. Pagination
support and defaults are operation-specific; Hodoflow does not promise one
global default for every generated collection.

## Write documents

Write the resource type and supported attributes inside `data`:

```json
{
  "data": {
    "type": "dashboard",
    "attributes": {
      "name": "Fulfillment health",
      "description": "Operational delivery metrics"
    }
  }
}
```

Do not copy fields from a read response into a write blindly. IDs, derived
values, organization/workspace context, timestamps, and read-only attributes
may be server-controlled. Inspect the operation's request-body fields in the
reference.

## Relationships, includes, and sparse fields

Where an operation declares support:

- `include=relationship.path` asks the response to sideload related resources;
- `fields[type]=field_a,field_b` limits attributes for one resource type; and
- relationship linkage appears under a resource object's `relationships` map.

Request only what the client consumes. An empty allowed-include pattern means
that operation exposes no relationship include, even if the internal resource
has relationships.

## Response headers

Successful and failed JSON:API responses expose:

- `x-api-version: v1` — the path-versioned JSON:API contract;
- `x-request-id` — the correlation ID to retain for logs and support;
- `Retry-After` on rate limits and some transient failures; and
- `idempotency-replayed: true` when a completed unsafe response is replayed.

Continue with [Pagination, filtering, and sorting](/platform/pagination-filtering-sorting),
[Errors and request IDs](/platform/errors-request-ids), and
[Idempotency and retries](/platform/idempotency-retries).
