OpenAPI reference · Media
Generate an image into the media library asynchronously
/media/generationsKick off an AI raster generation (kind: PHOTO via
gpt-image on Azure OpenAI, PHOTO_EDIT / IMAGE_EDIT via fal
nano-banana-2/edit). The handler validates the recipe, resolves
every media id through the same reachability rules as
GET /v1/media (owned + profile-assigned, READY only — raw
URLs are never accepted), atomically reserves AI-spend
capacity, enqueues an async job, and returns a Job envelope.
On completion the job's result carries the new asset as
{ mediaId: "img_…" }, usable with GET /v1/media and
PATCH /v1/posts/{postId}/media.
Cost: counts against the daily AI-spend cap (~6¢ for PHOTO, ~11¢ for the edit kinds, reconciled with provider actuals after the job runs). The reservation is a single atomic conditional update — concurrent calls cannot jointly exceed the cap; losers receive a 402.
wait_for_completion_ms is a soft hint — the server polls
for up to that many milliseconds (capped at 25 000 ms) before
returning.
Requires the media:write scope.
Authorization
AuthorizationstringrequiredBearer token in the Authorization header.
Pass
Authorization: Bearer scripe_sk_live_<...>(orscripe_sk_test_<...>for test keys) on every request. Keys are scoped to a single workspace and can be revoked from the Scripe dashboard.The same header also accepts an OAuth 2.1 access token (
scripe_oat_*); both credentials share one scope vocabulary and every operation below documents the scope it requires. An API key can hold every scope named on this surface exceptwebhooks:manage, which is grantable to OAuth tokens only today — the webhook-endpoint operations answer403 scope_missingto every API key. Operations that name no scope accept any valid token of the workspace.
Header parameters
Scripe-Api-VersionstringPin the API version. Format
YYYY-MM-DD. Omit to receive the currently rolling default. Unknown versions return400 version_unsupported.Idempotency-KeystringOpaque string (1–64 chars,
[A-Za-z0-9_-]) used to dedup retried writes. Within 24h of the first request, the same key- same body returns the original response (
Idempotent-Replayed: true). Same key + different body returns409 idempotency_key_conflict.
Strongly recommended for every write — see
/docs/api/v1/idempotency.- same body returns the original response (
Request bodyapplication/json
projectIdstringrequiredkindstringrequiredPHOTO: original AI image (optionally style-referenced).PHOTO_EDIT: compose the author's own photo(s) into a desired look.IMAGE_EDIT: targeted in-place tweak of an existing generated image.Allowed values:
PHOTO,PHOTO_EDIT,IMAGE_EDITpromptAssetstringStyling/format instructions — look-and-feel only. On
PHOTOandPHOTO_EDITthe workspace's saved branding is available material: it is applied when the instructions ask for it (for example "in our branding"), never forced onto a run that asked for a different look.subjectstringThe core idea/intention the visual communicates.
steerstringExplicit instruction that takes priority. For
IMAGE_EDITthis is the change to apply.referenceModestringPHOTOonly.style(default) draws loose inspiration from the references;replicatefaithfully recreates their composition.Allowed values:
style,replicatereferenceMediaIdsstring[]Up to 3 media ids used as style/look references. Media ids only — URLs are never accepted.
subjectMediaIdsstring[]PHOTO_EDITonly: the author's own photo(s) whose likeness must be preserved.baseMediaIdstringIMAGE_EDITonly: the generated image to edit in place. Must belong to the project itself.wait_for_completion_msintegerSoft hint — server polls for up to this many ms before returning. Capped at 25 000 ms. Larger values are silently clamped.
Responses
- 200
Job enqueued (or finished, on a sync-wait hit).
- 400
Malformed request (bad cursor, bad limit, etc.).
- 401
Missing, malformed, expired, or revoked API key.
- 402
Daily AI-spend cap reached for this workspace. Resets at 00:00 UTC.
- 403
Plan not eligible, scope missing, or workspace mismatch.
- 404
Resource not found in this workspace.
- 409
Idempotency-Keyreused with a different body within the 24h dedup window. Pick a fresh key or replay the original body verbatim. - 422
Body shape was JSON but failed validation (
unprocessable). - 429
Sliding-window rate limit exceeded.
Example request
curl --request POST \
--url 'https://api.scripe.io/v1/media/generations' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"projectId": "proj_a1b2c3d4e5f6g7h8",
"kind": "PHOTO",
"promptAsset": "string",
"subject": "string",
"steer": "string",
"referenceMode": "style",
"referenceMediaIds": [
"img_a1b2c3d4e5f6g7h8"
],
"subjectMediaIds": [
"img_a1b2c3d4e5f6g7h8"
],
"baseMediaId": "img_a1b2c3d4e5f6g7h8",
"wait_for_completion_ms": 0
}'Example response (200)
{
"data": {
"id": "job_a1b2c3d4e5f6g7h8",
"type": "POST_GENERATION",
"status": "QUEUED",
"projectId": "string",
"startedAt": "2026-08-10T09:00:00Z",
"completedAt": "2026-08-10T09:00:00Z",
"progress": {
"progress": 0,
"message": "string",
"updatedAt": "2026-08-10T09:00:00Z"
},
"result": {},
"errorCode": "string",
"errorMessage": "string",
"attemptCount": 0,
"estimatedCompletionMs": 0,
"createdAt": "2026-08-10T09:00:00Z",
"updatedAt": "2026-08-10T09:00:00Z"
}
}