OpenFill is in development. Inference is off, but is tested end to end, and will switch on at launch. All data currently on the site is for live testing: it will be erased at launch.

Skip to content
openfill

Detached orders

To avoid holding a connection while a low price waits, detach the request. You get 202 and an order id at once, the order waits on your behalf, and you collect the result when it is done.

Submitting

Pass detached: true on a chat or completion request. Disconnecting never cancels a detached order. Detaching does not change how long an order waits: a price-locked order still expires with its window (10 seconds), so leave the lock off for a request that must wait for a low level. stream and detached cannot be combined.

submit
curl https://api.openfill.ai/v1/chat/completions \  -H "Authorization: Bearer $OPENFILL_API_KEY" -H "Content-Type: application/json" \  -d '{"messages": [{"role":"user","content":"hello"}],       "model": "placeholder-large",       "max_price": 0.05, "detached": true}'
Response
202 {"id": "<order_id>", "object": "order", "status": "queued", "expires_at": "...",     "result_url": "/v1/orders/<order_id>/result",     "result_stored": true, "result_retention_days": 7}
FieldMeaning
idThe order id. Every later call names it.
statusqueued on a fresh submission. On an idempotent replay, the original order's current status.
expires_atWhen the order leaves the book unexecuted: your timeout, or the lock window.
result_urlWhere the body will be.
result_storedWhether a result will be kept. false when storage is off for this request.
result_retention_daysHow long it is kept, or 0.
warningPresent only when result_stored is false, saying the result URL will answer 410.

Caution

Data storage is off by default, and with it off a detached result is never stored, so the result endpoint returns 410 once the order finishes. Turn it on in Settings if you intend to collect results later. The storage page has the rules.

Collecting the result

collect
curl https://api.openfill.ai/v1/orders/<order_id>/result \  -H "Authorization: Bearer $OPENFILL_API_KEY"
Response
{"status": "done", "result": { ...the full chat completion... }}{"status": "done", "result": null, "result_pending": true}   # not written yet, retry{"status": "expired", "error": "...", "result": null}        # terminal, stop polling

Branch on status: it is the field that says whether the order has finished. Every answer carries id, status, created_at, expires_at and result_expires_at, then one of the shapes below.

Order statusAnswer
queued200 with result: null and queue_position, the order's place in the book.
executing200 with result: null.
done, result stored200 with result, the full completion body. It can be read as many times as you like until it expires.
done, still being written200 with result: null and result_pending: true, plus a Retry-After header. Poll again.
done, nothing stored410 result_unavailable. The message says whether storage was off, the result aged out, or you deleted it.
error, canceled, expired200 with result: null and a populated error. Final; nothing further will arrive.

Poll at a gentle interval. The result endpoint shares the per-account order budget on limits, and each body read counts against the hourly download allowance there.

Deleting a stored result

DELETE /v1/orders/{id}/result removes the body from storage ahead of your retention period and answers deleted: true. Deleting is idempotent, so a retry after a dropped response is not an error, and it does not change what the request was billed: the order and its charge stay in your history. Deleting before the order has run marks it, and the result is never stored.

Two cases are refused.

CaseWhat happens
The durable write has not landed yetRefused with 409 result_write_pending until it has, with Retry-After. Deleting mid-write would leave the order pointing at a body that is gone.
The result belongs to a batch that is still runningRefused with 409 batch_in_progress until the batch finishes, since its output file needs it.

Per-request storage controls

Any request may send "store": false to retain nothing durably for that call, or "retention_days": N to keep it for a shorter window than your account setting. Both can only shorten storage: your account policy is the outer bound. Lowering your account setting also shortens data already stored.

Detached and idempotent

A detached request that carries an Idempotency-Key is safe to resend: the replay answers 202 again with the same order id and the order's current status. One order exists for the key, however many times it is sent.

Following an order without its body

GET /v1/orders/{id} reports status, queue position, what the order cleared at and any error, whatever your storage setting. It is the call to make while an order waits.