---
title: "Conventions"
description: "Pagination, dates, limits and response headers."
canonical: "https://atelier201.com/docs/api/conventions"
updated: "2026-11-06"
---

# Conventions

## Envelopes

Every successful response is `{ "data": ..., "request_id": "..." }`. Quote the
`request_id` when you report a problem; it is how a log line is found.

## Pagination

Cursor-based, never offset. Pass the `next_cursor` from the previous response
back as `cursor`.

An offset walks the whole prefix on every page and, worse, SKIPS rows when
something is inserted between two requests, so a client paging through a list
that is being written to silently misses items. A cursor cannot.

## Forgiving inputs

`limit` is clamped, not rejected: asking for 500 gets you 100 and the response
reports the limit that was applied. A non-numeric limit still fails, because
that is a mistake rather than an intent.

Dates accept `2026-07-01` or a full ISO 8601 timestamp. A date-only value on
the `to` side means the END of that day, which is what a person means by "up to
the 31st".

## Writing safely

Every write that replaces something can say what it expects to replace. Send the
`expected_hash` of a file or entry you read, and the change is refused with
`409 conflict` if it moved. Publishing, rolling back and unpublishing take the
`expected_generation` you read, so you only change the state you reviewed. Both
conflicts carry what you need to read again in `error.details`.

## Long operations

A build returns at once with a `queued` state and you poll it until it is
`ready`, `failed` or `cancelled`. Those are final: stop polling when you see one.

## Rate limits

Five limits apply, and they defend different things: per-credential throughput,
a short burst window, per-IP volume, client registration, and authentication
FAILURES specifically. Every response carries the remaining budget in its
headers; a 429 carries `Retry-After`.
