Skip to content

Conventions

Behaviors shared by every endpoint in the Public API v2.

Identifiers

All resources are identified by a public_id — a stable, opaque string. Internal numeric IDs are never exposed. When creating relationships between resources (e.g., assigning content to a user), reference them by their public_id.

public_id values are UUIDs in canonical form. Treat them as opaque strings — do not parse or generate them yourself.

Pagination

List endpoints return a paginated envelope:

{
  "data": [ /* up to page_size items */ ],
  "meta": {
    "page": 1,
    "page_size": 25,
    "total_count": 137,
    "total_pages": 6
  }
}

Control pagination with these query parameters:

Parameter Default Max Description
page 1 1-indexed page number.
page_size 25 100 Items per page.

Sorting

List endpoints support ordering with a comma-separated list of fields. Prefix with - for descending order:

GET /users?ordering=-created,last_name

The supported fields per endpoint are listed in the API reference.

Filtering

Most list endpoints accept resource-specific filters as query parameters — for example GET /users?email=jane.doe@acme.com or GET /content-items?content_type=video&is_archived=false. The supported filters are listed in the API reference for each endpoint.

Errors

All errors follow a consistent envelope:

{
  "error": {
    "code": "not_found",
    "message": "Content item not found.",
    "request_id": "req_a1b2c3d4"
  }
}

Validation errors include field-level details:

{
  "error": {
    "code": "validation_error",
    "message": "Validation failed.",
    "request_id": "req_a1b2c3d4",
    "field_errors": {
      "email": ["A user with this email already exists."]
    },
    "non_field_errors": ["Cannot assign archived content."]
  }
}

Error codes

HTTP status code Meaning
400 bad_request Malformed request.
401 unauthenticated / invalid_token Missing or invalid token.
403 forbidden Authenticated, but the operation is not permitted.
404 not_found Resource does not exist or is not visible to this token.
409 conflict / duplicate The operation conflicts with the current state.
412 precondition_failed If-Match ETag did not match the current resource.
422 validation_error Request body failed validation.
429 rate_limited Too many requests; see Rate limits.
500 internal_error Unexpected server error. Quote the request_id to support.

Always log request_id with every failure — it's the fastest path to a resolution.

Rate limits

All endpoints are rate-limited. Specific per-tier limits are not yet published; the service returns sensible defaults during the preview.

Every response includes rate-limit headers:

Header Description
X-RateLimit-Limit Your rate limit (requests per window).
X-RateLimit-Remaining Requests remaining in the current window.
X-RateLimit-Reset Seconds until the limit resets.

When a request is rate-limited, the response is HTTP 429 with the standard error envelope and a Retry-After header.

ETags and concurrency

Resources that support optimistic concurrency return an ETag header on GET and require If-Match on PATCH. A mismatched ETag returns HTTP 412 precondition_failed — re-fetch the resource and retry.

Bulk endpoints

Bulk endpoints (e.g. POST /content-items/bulk/archive) operate on up to 100 resources per request. Per-item failures are isolated — a partial batch returns HTTP 207 Multi-Status with a per-item result list.