Docs menu

Generations API reference

Turn a screenshot into a store-ready marketing image.

View as Markdown

List generations

GET /generations

Auth: API key with scope generations:read or generations:write, or access token.

Requires generations:read or generations:write. Generations of the account that are not deleted (every API key and environment), newest first.

Credits. Free: no credits.

Parameters

Name In Type Description
limit query integer 1–100, default 20. Default: 20
cursor query string nextCursor of the previous page.
status query GenerationStatus
metadata query string <key>:<value>: only generations whose metadata has exactly this value.
screenshotSetId query string Only the images of this screenshot set (every attempt). Format: uuid
environment query ApiKeyEnvironment
source query GenerationSource
projectId query string Since 1.15.0: only generations of this project (its own images and the images of its screenshot sets), or none for generations in no project.

Responses

200 A page of generations.

Schema GenerationList (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Example 200 response
{
  "data": [
    {
      "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
      "status": "succeeded",
      "environment": "live",
      "inputs": [
        {
          "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
          "sourceUrl": null
        }
      ],
      "store": "app_store",
      "device": "app_store_1290x2796",
      "size": {
        "width": 1290,
        "height": 2796
      },
      "orientation": "portrait",
      "app": {
        "name": "Trailmate",
        "description": "Offline hiking maps"
      },
      "caption": "Find every trail, even offline",
      "palette": [
        {
          "hex": "#0F766E",
          "name": "Teal"
        }
      ],
      "logo": null,
      "metadata": {
        "campaign": "spring",
        "locale": "en-US"
      },
      "creditsCharged": 1,
      "creditsRefunded": 0,
      "result": {
        "image": {
          "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
          "contentType": "image/png",
          "width": 1290,
          "height": 2796
        },
        "thumbnail": {
          "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
          "contentType": "image/webp"
        },
        "urlsExpireAt": "2026-10-22T10:15:00.000Z",
        "caption": "Find every trail, even offline",
        "palette": [
          {
            "hex": "#0F766E",
            "name": "Teal"
          }
        ]
      },
      "error": null,
      "createdAt": "2026-10-22T10:00:00.000Z",
      "startedAt": "2026-10-22T10:00:01.000Z",
…

Shortened; the Markdown version has the full example.

400 INVALID_INPUT. A credential sent in the query string is refused before authentication, without RateLimit headers.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

401 UNAUTHORIZED: missing, malformed, unknown, revoked or expired credential.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id

403 FORBIDDEN: see details.reason.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

429 RATE_LIMITED: the request rate of the API key (details.scope key) or of the account (user) is exhausted for this window, or too many failed authentication attempts came from this IP (no details.scope and no RateLimit headers). Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

default Error (see ErrorEnvelope and /v1/docs/errors).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Create a generation

POST /generations

Auth: API key with scope generations:write, or access token.

Requires generations:write. Turns one screenshot into one store-ready marketing image of exactly the requested size. Costs 1 credit with a live key, charged now and refunded if the generation fails or is canceled before it starts; test keys (ss_test_…) are free and return a sample image. Answers 202 with the queued generation (poll GET /generations/{id}), or 200 when it is already final (after Prefer: wait, or a replay of a finished one). Send an Idempotency-Key so a retried request never creates (or charges) twice.

When to use. For one image (one screenshot, one device). For a whole listing (several screens, devices or both stores) use POST /screenshot-sets instead.

Credits. 1 credit with a live key, charged at create and refunded automatically if the generation fails or is canceled before it starts; free with a test key (ss_test_…). Without enough credits: 402 INSUFFICIENT_CREDITS, nothing created.

Parameters

Name In Type Description
wait query integer Seconds (0–60) to hold the response until the generation finishes. Overrides Prefer: wait.
idempotency-key header string 1–255 printable ASCII characters. Retrying with the same key and body returns the original generation (Idempotent-Replayed: true) instead of creating and charging another. Keys are kept as long as the generation exists.
prefer header string wait=<seconds> (at most 60): hold the response until the generation finishes.

Request body application/json

Required. Schema CreateGenerationRequest.

FieldTypeDescription
inputsrequiredarray of GenerationInputExactly one screenshot in this version.
storerequiredStoreTarget
devicestringA GET /devices id of the same store. Exactly one of device and size is required.
sizeGenerationSize
orientationOrientationDefault: from size (wider than tall is landscape), else portrait (the feature graphic: landscape). Must agree with the size and the device.
apprequiredobject
app.namerequiredstring
app.descriptionstringDefault: ""
captionstringThe marketing caption. Absent or blank: derived from the screenshot.
palettearray of PaletteColor1–8 colours. Absent: extracted from the screenshot.
logoGenerationInputYour app icon or logo (any shape; PNG, JPEG or WebP).
metadataGenerationMetadata
projectIdstringSince 1.15.0: put the generation in this project of yours (GET /projects). The project does not change how it is generated.Format: uuid
styleIdstringSince 1.18.0: a style of yours (GET /styles). It fills palette and logo when you leave them out and adds its background mood, description and caption tone. It is copied into the generation: editing or deleting the style later changes nothing here.Format: uuid
Example request body
{
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a"
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  }
}

Responses

200 Final already (waited, or a replay of a finished generation).

Schema Generation (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Preference-Applied , Vary , Location , Idempotent-Replayed

Example 200 response
{
  "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
  "status": "succeeded",
  "environment": "live",
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
      "sourceUrl": null
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "size": {
    "width": 1290,
    "height": 2796
  },
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "logo": null,
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  },
  "creditsCharged": 1,
  "creditsRefunded": 0,
  "result": {
    "image": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
      "contentType": "image/png",
      "width": 1290,
      "height": 2796
    },
    "thumbnail": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
      "contentType": "image/webp"
    },
    "urlsExpireAt": "2026-10-22T10:15:00.000Z",
    "caption": "Find every trail, even offline",
    "palette": [
      {
        "hex": "#0F766E",
        "name": "Teal"
      }
    ]
  },
  "error": null,
  "createdAt": "2026-10-22T10:00:00.000Z",
  "startedAt": "2026-10-22T10:00:01.000Z",
  "finishedAt": "2026-10-22T10:00:24.000Z",
  "deletedAt": null,
…

Shortened; the Markdown version has the full example.

202 Accepted: queued or running.

Schema Generation (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Preference-Applied , Vary , Location , Idempotent-Replayed

Example 202 response
{
  "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
  "status": "succeeded",
  "environment": "live",
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
      "sourceUrl": null
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "size": {
    "width": 1290,
    "height": 2796
  },
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "logo": null,
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  },
  "creditsCharged": 1,
  "creditsRefunded": 0,
  "result": {
    "image": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
      "contentType": "image/png",
      "width": 1290,
      "height": 2796
    },
    "thumbnail": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
      "contentType": "image/webp"
    },
    "urlsExpireAt": "2026-10-22T10:15:00.000Z",
    "caption": "Find every trail, even offline",
    "palette": [
      {
        "hex": "#0F766E",
        "name": "Teal"
      }
    ]
  },
  "error": null,
  "createdAt": "2026-10-22T10:00:00.000Z",
  "startedAt": "2026-10-22T10:00:01.000Z",
  "finishedAt": "2026-10-22T10:00:24.000Z",
  "deletedAt": null,
…

Shortened; the Markdown version has the full example.

400 INVALID_INPUT. A credential sent in the query string is refused before authentication, without RateLimit headers.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

401 UNAUTHORIZED: missing, malformed, unknown, revoked or expired credential.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id

402 INSUFFICIENT_CREDITS: nothing was created or charged. See details.availableCredits and details.topUpUrl.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

403 FORBIDDEN: see details.reason.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

409 IDEMPOTENCY_CONFLICT (the Idempotency-Key was used for a different request; details.generationId) or UPLOAD_NOT_READY (an input upload is not usable; details.reason, details.path).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

413 PAYLOAD_TOO_LARGE (the JSON body is over 1 MB; refused before authentication, without RateLimit headers) or IMAGE_TOO_LARGE (a URL input is too large; see details.reason).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

415 UNSUPPORTED_FORMAT: not a PNG, JPEG or WebP image (see details.reason).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

422 NOT_A_SCREENSHOT (an input is not screenshot-sized; details.path) or URL_FETCH_FAILED (a URL input could not be fetched; see details.reason).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

429 RATE_LIMITED: the request rate of the API key (details.scope key) or of the account (user) is exhausted for this window, or too many failed authentication attempts came from this IP (no details.scope and no RateLimit headers). Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

503 SERVICE_UNAVAILABLE: uploads are busy. Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

default Error (see ErrorEnvelope and /v1/docs/errors).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Get a generation

GET /generations/{id}

Auth: API key with scope generations:read or generations:write, or access token.

Requires generations:read or generations:write. Includes deleted generations (deletedAt set, result null). Every call returns freshly signed result URLs (valid 15 minutes). Prefer: wait=<seconds> (or ?wait) holds the response until it is final.

When to use. To poll a generation every 2–5 seconds (or once with Prefer: wait=60) until status is succeeded, failed or canceled, and for fresh result URLs.

Credits. Free: no credits.

Parameters

Name In Type Description
id required path string Generation id. An unknown or malformed id is 404.
wait query integer Seconds (0–60) to hold the response until the generation finishes. Overrides Prefer: wait.
prefer header string wait=<seconds> (at most 60): hold the response until the generation finishes.

Responses

200 Final: succeeded, failed or canceled.

Schema Generation (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Preference-Applied , Vary

Example 200 response
{
  "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
  "status": "succeeded",
  "environment": "live",
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
      "sourceUrl": null
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "size": {
    "width": 1290,
    "height": 2796
  },
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "logo": null,
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  },
  "creditsCharged": 1,
  "creditsRefunded": 0,
  "result": {
    "image": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
      "contentType": "image/png",
      "width": 1290,
      "height": 2796
    },
    "thumbnail": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
      "contentType": "image/webp"
    },
    "urlsExpireAt": "2026-10-22T10:15:00.000Z",
    "caption": "Find every trail, even offline",
    "palette": [
      {
        "hex": "#0F766E",
        "name": "Teal"
      }
    ]
  },
  "error": null,
  "createdAt": "2026-10-22T10:00:00.000Z",
  "startedAt": "2026-10-22T10:00:01.000Z",
  "finishedAt": "2026-10-22T10:00:24.000Z",
  "deletedAt": null,
…

Shortened; the Markdown version has the full example.

202 Not final yet: queued or running.

Schema Generation (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Preference-Applied , Vary

Example 202 response
{
  "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
  "status": "succeeded",
  "environment": "live",
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
      "sourceUrl": null
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "size": {
    "width": 1290,
    "height": 2796
  },
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "logo": null,
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  },
  "creditsCharged": 1,
  "creditsRefunded": 0,
  "result": {
    "image": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
      "contentType": "image/png",
      "width": 1290,
      "height": 2796
    },
    "thumbnail": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
      "contentType": "image/webp"
    },
    "urlsExpireAt": "2026-10-22T10:15:00.000Z",
    "caption": "Find every trail, even offline",
    "palette": [
      {
        "hex": "#0F766E",
        "name": "Teal"
      }
    ]
  },
  "error": null,
  "createdAt": "2026-10-22T10:00:00.000Z",
  "startedAt": "2026-10-22T10:00:01.000Z",
  "finishedAt": "2026-10-22T10:00:24.000Z",
  "deletedAt": null,
…

Shortened; the Markdown version has the full example.

400 INVALID_INPUT. A credential sent in the query string is refused before authentication, without RateLimit headers.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

401 UNAUTHORIZED: missing, malformed, unknown, revoked or expired credential.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id

403 FORBIDDEN: see details.reason.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

404 NOT_FOUND: no such resource for this caller.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

429 RATE_LIMITED: the request rate of the API key (details.scope key) or of the account (user) is exhausted for this window, or too many failed authentication attempts came from this IP (no details.scope and no RateLimit headers). Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

default Error (see ErrorEnvelope and /v1/docs/errors).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Delete a generation

DELETE /generations/{id}

Auth: API key with scope generations:write, or access token.

Requires generations:write. Deletes the result files of a finished generation now; the generation keeps its metadata with deletedAt set and no longer appears in lists. Idempotent. A queued or running generation cannot be deleted (409 GENERATION_STATE_CONFLICT): cancel it or wait.

Credits. Free: no credits and no refund (the image was made).

Parameters

Name In Type Description
id required path string Generation id. An unknown or malformed id is 404.

Responses

204 Deleted.

Headers: X-Request-Id , RateLimit , RateLimit-Policy

400 INVALID_INPUT. A credential sent in the query string is refused before authentication, without RateLimit headers.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

401 UNAUTHORIZED: missing, malformed, unknown, revoked or expired credential.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id

403 FORBIDDEN: see details.reason.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

404 NOT_FOUND: no such resource for this caller.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

409 GENERATION_STATE_CONFLICT: not possible in the current status (details.status, details.action).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

429 RATE_LIMITED: the request rate of the API key (details.scope key) or of the account (user) is exhausted for this window, or too many failed authentication attempts came from this IP (no details.scope and no RateLimit headers). Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

default Error (see ErrorEnvelope and /v1/docs/errors).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Cancel a generation

POST /generations/{id}/cancel

Auth: API key with scope generations:write, or access token.

Requires generations:write. Only a queued generation that has not started can be canceled; its credit is refunded. Canceling a canceled generation returns it again. Once it is running it cannot be canceled (409 GENERATION_STATE_CONFLICT).

Credits. Free; refunds the credit of a generation that had not started.

Parameters

Name In Type Description
id required path string Generation id. An unknown or malformed id is 404.

Responses

200 Canceled.

Schema Generation (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

Example 200 response
{
  "id": "0b8e7a52-41c6-4f38-9d0e-7f6a1c2b3d4e",
  "status": "succeeded",
  "environment": "live",
  "inputs": [
    {
      "uploadId": "6f1c1f0e-8a5e-4b8e-9a51-0f0e1d2c3b4a",
      "sourceUrl": null
    }
  ],
  "store": "app_store",
  "device": "app_store_1290x2796",
  "size": {
    "width": 1290,
    "height": 2796
  },
  "orientation": "portrait",
  "app": {
    "name": "Trailmate",
    "description": "Offline hiking maps"
  },
  "caption": "Find every trail, even offline",
  "palette": [
    {
      "hex": "#0F766E",
      "name": "Teal"
    }
  ],
  "logo": null,
  "metadata": {
    "campaign": "spring",
    "locale": "en-US"
  },
  "creditsCharged": 1,
  "creditsRefunded": 0,
  "result": {
    "image": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png?X-Amz-Expires=900&X-Amz-Signature=abc123",
      "contentType": "image/png",
      "width": 1290,
      "height": 2796
    },
    "thumbnail": {
      "url": "https://storage.example.com/platform/users/5b0c7d2e-1f3a-4c5b-8d6e-7f8091a2b3c4/generations/job-9a8b7c6d-5e4f-4a3b-9c2d-1e0f9a8b7c6d-a1.png.thumb.webp?X-Amz-Expires=900&X-Amz-Signature=def456",
      "contentType": "image/webp"
    },
    "urlsExpireAt": "2026-10-22T10:15:00.000Z",
    "caption": "Find every trail, even offline",
    "palette": [
      {
        "hex": "#0F766E",
        "name": "Teal"
      }
    ]
  },
  "error": null,
  "createdAt": "2026-10-22T10:00:00.000Z",
  "startedAt": "2026-10-22T10:00:01.000Z",
  "finishedAt": "2026-10-22T10:00:24.000Z",
  "deletedAt": null,
…

Shortened; the Markdown version has the full example.

400 INVALID_INPUT. A credential sent in the query string is refused before authentication, without RateLimit headers.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

401 UNAUTHORIZED: missing, malformed, unknown, revoked or expired credential.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id

403 FORBIDDEN: see details.reason.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

404 NOT_FOUND: no such resource for this caller.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

409 GENERATION_STATE_CONFLICT: not possible in the current status (details.status, details.action).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy

429 RATE_LIMITED: the request rate of the API key (details.scope key) or of the account (user) is exhausted for this window, or too many failed authentication attempts came from this IP (no details.scope and no RateLimit headers). Retry after Retry-After seconds.

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy , Retry-After

default Error (see ErrorEnvelope and /v1/docs/errors).

Schema ErrorEnvelope (application/json).

Headers: X-Request-Id , RateLimit , RateLimit-Policy