For AI agents: this page is also available as Markdown at https://docs.refabric.com/api-reference/platform/conventions.md, and the index of every page is https://docs.refabric.com/llms.txt.
Platform API
Conventions
Rules that hold across every endpoint.
Requests
- JSON bodies,
Content-Type: application/json(uploads may usemultipart/form-data). - Field names are
snake_case. - A task's input takes exactly the fields in its schema (
GET /v1/tasks/{name}). Any other field — a misspelled name, or one the server fills itself — is refused with422 field_not_accepted, andfieldnames it, so a typo shows up on the first call. (This rule is for the task input; query parameters work as each endpoint documents them.) Known fields are validated — a wrong type, a value out of range or a missing required field is a422naming thefield.
Pagination
List endpoints use cursors.
GET /v1/jobs?limit=50{ "items": [ … ], "has_more": true, "next_cursor": "AXsiZiI6IjQ0MTM2ZmEzNTVi…" }limit: page size (default and maximum per endpoint in the OpenAPI spec).has_moresays whether another page follows. While it istrue, passcursor=<next_cursor>for the next page. On the last pagehas_moreisfalseandnext_cursoris absent.- Cursors are opaque; do not build or parse them. They may expire — restart the listing if one is refused.
- Order is newest first unless an endpoint says otherwise (a job result's
filesare in the order the task documents — Jobs).
def all_items(session, url, **params):
cursor = None
while True:
page = session.get(url, params={**params, **({"cursor": cursor} if cursor else {})}).json()
yield from page["items"]
if not page["has_more"]:
return
cursor = page["next_cursor"]Time
ISO-8601 in UTC with a Z suffix: 2026-09-28T10:00:00Z. Fractional seconds may appear. Durations
in a body are integer milliseconds, and their field says so (duration_ms, wait_ms,
run_ms); a setting whose name ends in _seconds (limits.*.max_seconds of GET /v1/meta,
grace_period_seconds) says seconds the same way. Header values stay in seconds
(Retry-After, Prefer: wait=N), and webhook X-Refabric-Timestamp is Unix seconds, because it
is part of a signed message.
Ids
All ids and references are opaque strings (j_…, art:…, file:…, req_…, key_…).
Do not parse them, assume a length, or build them. Compare them as exact strings.
Enums
Every closed option in an input schema lists its allowed values, each with a description.
- Inputs: only the listed values are accepted.
- Outputs: new values may appear at any time (for example a new job status or error type). Your code must tolerate unknown values — treat them as "other", not as an error.
Nulls and missing fields
- In responses, a field that has no value is present with
null, unless the schema marks it optional. - New response fields may be added at any time; ignore fields you do not know.
- In requests, omitting an optional field and sending
nullmean the same thing: use the default.
Numbers and money
Credits are whole numbers (integers) in the account's credit unit, sent as integers. They appear
in X-Refabric-Credits, the estimate response, and account endpoints — never inside job results. Prices per task:
Pricing.
Headers
| Header | Direction | Meaning |
|---|---|---|
Authorization / x-api-key | request | Authentication |
Idempotency-Key | request | Idempotency |
X-Request-ID | both | your correlation id (optional) inbound; our request_id always outbound |
X-Client-Request-ID | response | your X-Request-ID, echoed when it was a valid one |
Prefer: wait=N | request | sync mode |
X-Refabric-Start-Timeout | request | start deadline |
Refabric-Version | request | dated version pin |
X-Refabric-Credits, X-Refabric-Credit-Type | response | on the submit answer (POST /v1/tasks/{name}) only, and only when the task costs credits: the credits held, and their credit_type (the same value /estimate and GET /v1/pricing answer) |
X-Refabric-Error-Type | response | the error.type of an error response |
X-Refabric-Start-Timeout-Type | response | user when a job failed its start deadline |
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After | response | Rate limits |
Every response, success or error, carries X-Request-ID — always OUR id (req_…). If you send
X-Request-ID (at most 128 characters of A-Z a-z 0-9 . _ : -), we log it next to ours and echo it
back as X-Client-Request-ID; anything else is ignored, never refused.