Skip to content

Image operations

Saved image operations, scoped downloads and unknown-outcome handling.

No current prepared translation is available. The English source is shown without machine translation.

Image operations and files

A creation returns a persistent operation even when the client stops waiting. Continue using the same active API key. Operations and output files are scoped to the owner, principal, API key and current group, not merely to a guessed ID.

RequestResult
GET /v1/images/operationsYour scoped history, up to 50 rows; pass before=next_cursor for the next page
GET /v1/images/operations/{id}Compact status and output descriptors; accounting via view=details
GET /v1/images/operations/{id}/resultCompleted created/data response; HTTP 202 while pending; mapped HTTP errors for explicit provider failures; HTTP 409 on other terminal states
GET /v1/images/operations/{id}/files/{index}Private output bytes with a zero-based index
POST /v1/images/operations/{id}/retry-downloadsEmpty-body download retry, without another generation

queued and preparing have not crossed the paid dispatch boundary. dispatching must never be automatically reclaimed for another POST. The saved provider response progresses through received and retrieving to completed. failed finishes without a new automatic attempt; an expired queue is reported as failed with error_code queue_expired, not a separate expired status.

outcome_unknown means the gateway cannot safely decide the paid POST's outcome. review_required means response or pricing information needs investigation. Neither is permission to start over with a new Idempotency-Key. Contact the operator; automated reconciliation is not implemented in this release.

For retrieval_failed, use the download-only endpoint at most five times before the 24-hour file expiry. It reads the already saved provider response and does not generate or account twice. Reads and replays do not require a new inference payment. Files expire, but idempotency tombstones remain so that an old key never silently starts a new request.

There is no advance reserve. accounting_recorded says an entry was committed for the existing settlement process; it does not promise the wallet has already been updated. Token-based quotes remain unknown until usable provider usage arrives. Playground no longer sends model_gate.max_cost_usd. The optional legacy field remains recognized only for a provable fixed quote.

Playground and lost HTTP responses (10.49.0)

Playground Images uses separate read/create/download-retry grants with current actor/key permissions. It does not relax legacy browser-key restrictions. A stored operation can continue after its short grant expires, while current session, key and access requirements still apply.

GET /v1/images/operations?idempotency_key=... is a read-only lookup under the same identity/key scope. A matching operation returns its saved public status; no visible match returns submission_found:false. This is not a signal to automatically create another intent: the original acceptance may still be in progress. Use the same key/intent and inspect history. No token, body, price or debit is created by lookup.

Read-only GET /v1/images/catalog?model=...&operation=... exposes separate reviewed route offers, not a guarantee of provider health. POST /v1/images/quote normalizes supported settings and supplies an uncharged approval fingerprint. The index and direct creation endpoints remain available to ordinary API clients.

Catalog and saved fields

GET /v1/images/catalog requires model; operation defaults to image.generate and also accepts image.edit. It returns object:list, separate data offers, runtime_limits, and provider_health_verified:false. An empty data list means no usable reviewed offer, not a supplier health test. Each offer exposes route/model/operation, contract revision/hash/expiry, request limits, the selected billing tariff and multipliers. No upstream credential is returned.

The explicit ?view=details response includes object:image.operation, id, operation, model, status, Unix created and files_expires_at, files_available, error_code, quote, usage, accounting_recorded, accounting_note, files, result_url and download_retry_allowed. Each file descriptor has index, relative URL, SHA-256, MIME, bytes and dimensions. An unexpired time flag alone does not guarantee an output has already been produced. Source images are not served by the output endpoint.

History is ordered by descending operation ID, at most 50 entries; it is not a chronological sort of externally supplied IDs. before cannot be combined with idempotency_key. The lookup response is a list with zero or one item and submission_found; not found is not proof that an in-flight create was rejected. Foreign resources are not disclosed.

Price quote and Usage Limit quote are preliminary values. Calculated cost is still distinct from a completed balance update. Saved-file availability requires an existing file and an unexpired download window. Aggregate-only token observations may appear in reported_tokens with token_usage_status=aggregate_only_not_priced; they do not supply a missing modality breakdown for token pricing. See generation response fields.

Settlement and saved supplier observations

Individual-operation GET and idempotency lookup with ?view=details include a read-only settlement object scoped to the same owner, principal, key and group. It has status, record_found, Unix settled_at, wallet_debited, usage_applied, and Unix observed_at. Unknown observations are JSON null. pending/failed have not established a completed debit; settled/recovered with a timestamp and positive recorded cost establish the recorded settlement event. not_required is distinct from a failed lookup. not_available means the matching accounting row is absent, possibly past retention; unavailable means observation failed. Neither means free work. Unobserved history rows can report not_checked; read the specific operation for a fresh observation. No observation creates a payment, refund or reservation.

supplier_http_status is the saved supplier status (0 before one is available), and response_saved indicates a recorded response timestamp. They are not the HTTP status of this API GET or of the original202 enqueue response. A saved5xx is not proof of no supplier cost. Do not automatically resubmit an unknown paid outcome.

Compact status and accounting details

Since version11.0.0, operation responses are compact by default: object, id, model, status, created, status_url, result_url. An actionable error_code or reported progress is included only when present. Completed results include availability, expiry and required file descriptors. Empty fields, quote, normalized usage, settlement and supplier diagnostics are omitted. Omission does not mean zero cost or a completed debit.

Use GET /v1/images/operations/{id}?view=details for the previous full authorized accounting view. Lists and result manifests also support the explicit details view where applicable. Reading details never generates new media or expands access. The quote endpoint remains the separate place to inspect an uncharged price calculation.

Read a result: Raw and cURL

Use the same active API key and actor context that created the operation. Another key under the same account does not automatically inherit its results. Current access and domain/IP restrictions are checked again. Get OPERATION_ID from the accepted creation response or your authorized history, and set MODEL_API_KEY locally without publishing the secret. A temporary Playground permission is not a reusable CLI credential; copying a command does not export or enlarge that permission.

GET https://api.model-gate.com/v1/images/operations/{id}/result
Authorization: Bearer <YOUR_API_KEY>
# status
curl --fail-with-body --request GET \
  --url "https://api.model-gate.com/v1/images/operations/${OPERATION_ID:?Set OPERATION_ID}" \
  --header "Authorization: Bearer ${MODEL_API_KEY:?Set MODEL_API_KEY}" \
  --output images-status.json

# result
curl --fail-with-body --request GET \
  --url "https://api.model-gate.com/v1/images/operations/${OPERATION_ID:?Set OPERATION_ID}/result" \
  --header "Authorization: Bearer ${MODEL_API_KEY:?Set MODEL_API_KEY}" \
  --output images-result.json

# first image (only when descriptor index 0 exists)
curl --fail-with-body --request GET \
  --url "https://api.model-gate.com/v1/images/operations/${OPERATION_ID:?Set OPERATION_ID}/files/0" \
  --header "Authorization: Bearer ${MODEL_API_KEY:?Set MODEL_API_KEY}" \
  --output image-0.bin

/result returns the saved created/data JSON response. A file endpoint returns actual image bytes, not that JSON. Select an existing zero-based index from the operation's file descriptors and choose an extension matching its MIME type; the example uses .bin rather than guessing PNG. Playground supplies the matching extension for each available image.

These are bodyless GET requests: no Content-Type, Idempotency-Key, quote, route_id or max_cost_usd is needed. Read status until it reports completion, then read the result/file. Pending, failed, expired and unauthorized responses are not output files; --fail-with-body returns a nonzero exit status for HTTP errors but may still write their body to the output filename. Check the status and content type before treating a downloaded body as media. Do not repeat a paid POST because a GET failed.

Playground's Get the result · Raw / cURL block generates these commands for the selected operation and its original key. They are examples of a new read, not a recording of an earlier HTTP exchange. Copying or switching command tabs makes no network request. Opening history or a saved result still performs its normal authorized read; it does not generate, reserve or charge again.

Explicit provider failures (14.11.2)

A complete provider error without an image result is a terminal failed operation. This includes a recognized error delivered with supplier HTTP 200 or 5xx. A malformed, incomplete or contradictory response remains unresolved; an error combined with output or ongoing work is not treated as a definite rejection.

The operation includes a controlled error object with message, type and public code. Supplier secrets and arbitrary response text are not echoed. Keep the operation id, status_url, Location and X-Request-ID for support. The internal error_code remains a diagnostic identifier.

Public error codeCreation/result HTTP responseMeaning
image_generation_failed502The provider could not complete image generation.
image_provider_error502The provider returned another recognized error.
invalid_image_request400The provider rejected request parameters.
content_policy_violation400The provider rejected the request under its content policy.
rate_limit_exceeded429The provider's request limit was reached.

If a definite provider failure finishes during synchronous creation, the response uses the HTTP error above and keeps the accepted image.operation fields alongside error. An identical replay under the original Idempotency-Key returns that same failed operation, including when async mode is requested. A newly accepted async operation still returns 202. GET /v1/images/operations/{id} returns HTTP 200 with status: failed and error, because it successfully reads the operation. /result returns the mapped error even after the normal result-file window expires. No image file is advertised for a failed operation.

billing_review_required: true means the failed generation has unresolved supplier-work accounting. It is separate from the generation status and from settlement.status. A complete supplier 4xx refusal other than 408 does not set this flag. Neither a false flag nor missing accounting proves zero cost or a completed settlement. Read the authorized details if the accounting state matters.

There is no automatic paid retry. A new generation requires an explicit new intent; preserve the original operation and inspect uncertain costs before deciding. Updating the application does not rewrite historical unresolved operations or their accounting.