The one rule
status alone does not signal success. A generation that fails at the provider is
normalized to status: "COMPLETED" with billingStatus: "failed" — the request finished,
but produced no billable output. Each surface exposes failure differently, so read the signal
that surface actually carries:
A client that treats status: "COMPLETED" as success will show failed generations as
successful. Always branch on the surface’s own signal above.
Terminal states
COMPLETED, FAILED and CANCELLED are terminal — a request never transitions away from them.
Two of the three carry caveats:
FAILED is rare. A generation that fails at the provider is normalized to COMPLETED (see
above); FAILED is what the platform writes when it force-fails a request that got stuck. A job
that exceeds a deployment’s execution timeout
follows the same normalization — COMPLETED with billingStatus: "failed" — not a resting
FAILED.
CANCELLED is reachable on deployment jobs. Pollers must include it in their terminal set or
they will spin forever on a cancelled job.
Cancellation
Cancellation depends on what the endpoint is.
Serverless GPU deployments: cancel is real. PUT (or GET) the cancel_url and the job is
stopped, the request goes terminal on CANCELLED with billingStatus: "failed" (zero charge), and
a completed webhook fires. An unconfirmed stop is never converted into a local CANCELLED — the
response carries the request’s real state instead, which may be COMPLETED. See
Cancel and terminal states.
Models and wrappers: cancellation is not supported. The cancel_url returned on submit is
reserved: requesting it returns the same body as status_url and does not stop the request.
Visibility
Requests are private by default: only the owner (and the platform) can read them.
PATCH /requests/{requestId}/visibility with { "public": true } publishes a request so it
can appear on catalog preview surfaces (for example as a model example). Publication is
all-or-nothing — there is no scoped sharing.
The same vocabulary applies to models with one important difference: a private model is
unlisted, not access-controlled. It is excluded from listings and search, but direct reads
by its owner/alias endpoint (model detail, its openapi.json, invoking it) still resolve.
Do not rely on model privacy as an ACL.
Rate limits
Limits are enforced per IP address at the edge; exceeding them returns HTTP 429 (without a
Retry-After header). Back off with jitter on 429. There are no per-key quotas today.