Webhooks API reference
Signed HTTPS callbacks when generations and sets finish.
List webhooks
GET /webhooks
Auth: API key with scope webhooks:read or webhooks:write, or access token.
Requires webhooks:read or webhooks:write. An API key sees the webhooks of its own environment; an access token sees both (or one with ?environment=). Secrets are never returned.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
environment | query | ApiKeyEnvironment |
Responses
200 Webhooks, newest first.
Schema WebhookList (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"data": [
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"environment": "live",
"url": "https://hooks.example.com/…shot",
"events": [],
"description": "string",
"enabled": true,
"creditsLowThreshold": 0,
"secret": {
"hint": "whsec_…Xy7Q",
"rotatedAt": "2026-10-21T12:00:00.000Z",
"previousExpiresAt": "2026-10-21T12:00:00.000Z"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z"
}
]
} 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 webhook
POST /webhooks
Auth: API key with scope webhooks:write, or access token.
Requires webhooks:write (not a default scope). Registers an https:// endpoint (port 443, public addresses only) for the given events of one environment; at most 10 per environment. The signing secret is in this response only.
When to use. Instead of polling, when you run an https endpoint that can receive callbacks; agents in a terminal usually poll.
Credits. Free: no credits.
Request body application/json
Required. Schema CreateWebhookRequest.
| Field | Type | Description |
|---|---|---|
urlrequired | string | An https:// URL on port 443, without credentials, at most 2048 characters, whose host resolves only to public addresses (checked now and before every delivery). Shown masked afterwards. |
eventsrequired | array of WebhookEventType | The business events to deliver (1–4, unique). |
description | string | Free text, at most 200 characters. |
enabled | boolean | Default true. |
creditsLowThreshold | integer | Default 5. |
environment | ApiKeyEnvironment | Which events the webhook receives: live or test (test-key generations and sets). Default: the API key environment (access tokens: live). An API key can only create webhooks of its own environment. |
{
"url": "https://hooks.example.com/storeshot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 1,
"environment": "live"
}Responses
201 Created. Store secret.value now; it is never shown again.
Schema WebhookWithSecret (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"environment": "live",
"url": "https://hooks.example.com/…shot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 0,
"secret": {
"hint": "whsec_…Xy7Q",
"rotatedAt": "2026-10-21T12:00:00.000Z",
"previousExpiresAt": "2026-10-21T12:00:00.000Z",
"value": "string"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z"
} 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
413 PAYLOAD_TOO_LARGE.
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id
422 WEBHOOK_URL_REJECTED: the host is not public or does not resolve (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: secrets cannot be issued right now.
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
default Error (see ErrorEnvelope and /v1/docs/errors).
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
Get a webhook
GET /webhooks/{id}
Auth: API key with scope webhooks:read or webhooks:write, or access token.
Requires webhooks:read or webhooks:write. The secret is never returned.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook id. An unknown or malformed id is 404. |
Responses
200 The webhook.
Schema Webhook (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"environment": "live",
"url": "https://hooks.example.com/…shot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 0,
"secret": {
"hint": "whsec_…Xy7Q",
"rotatedAt": "2026-10-21T12:00:00.000Z",
"previousExpiresAt": "2026-10-21T12:00:00.000Z"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z"
} 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 webhook
DELETE /webhooks/{id}
Auth: API key with scope webhooks:write, or access token.
Requires webhooks:write. Deletes the webhook with its delivery log; pending deliveries are dropped.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook 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
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
Update a webhook
PATCH /webhooks/{id}
Auth: API key with scope webhooks:write, or access token.
Requires webhooks:write. Send any of url, events, description, enabled, creditsLowThreshold. A new url is checked like on create. While a webhook is disabled it gets no new events, and a pending delivery reaching its next attempt is canceled.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook id. An unknown or malformed id is 404. |
Request body application/json
Required. Schema UpdateWebhookRequest.
| Field | Type | Description |
|---|---|---|
url | string | An https:// URL on port 443, without credentials, at most 2048 characters, whose host resolves only to public addresses (checked now and before every delivery). Shown masked afterwards. |
events | array of WebhookEventType | The business events to deliver (1–4, unique). |
description | string | Free text, at most 200 characters. |
enabled | boolean | |
creditsLowThreshold | integer | credits.low fires when the live balance falls below this many credits (1–10000). |
{
"url": "https://hooks.example.com/storeshot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 1
}Responses
200 The updated webhook.
Schema Webhook (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"environment": "live",
"url": "https://hooks.example.com/…shot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 0,
"secret": {
"hint": "whsec_…Xy7Q",
"rotatedAt": "2026-10-21T12:00:00.000Z",
"previousExpiresAt": "2026-10-21T12:00:00.000Z"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z"
} 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
413 PAYLOAD_TOO_LARGE.
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id
422 WEBHOOK_URL_REJECTED: the host is not public or does not resolve (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
Rotate the signing secret
POST /webhooks/{id}/rotate-secret
Auth: API key with scope webhooks:write, or access token.
Requires webhooks:write. Issues a new secret (in this response only). For gracePeriodSeconds (default 24 hours) deliveries carry a signature with each secret, so receivers can switch without dropping events.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook id. An unknown or malformed id is 404. |
Request body application/json
Optional. Schema RotateWebhookSecretRequest.
| Field | Type | Description |
|---|---|---|
gracePeriodSeconds | integer | How long the previous secret keeps signing deliveries next to the new one (0–604800, default 86400). 0 drops it at once. |
{
"gracePeriodSeconds": 0
}Responses
200 Rotated. Store secret.value now; it is never shown again.
Schema WebhookWithSecret (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"environment": "live",
"url": "https://hooks.example.com/…shot",
"events": [
"generation.succeeded"
],
"description": "string",
"enabled": true,
"creditsLowThreshold": 0,
"secret": {
"hint": "whsec_…Xy7Q",
"rotatedAt": "2026-10-21T12:00:00.000Z",
"previousExpiresAt": "2026-10-21T12:00:00.000Z",
"value": "string"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z"
} 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
413 PAYLOAD_TOO_LARGE.
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id
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: secrets cannot be issued right now.
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
default Error (see ErrorEnvelope and /v1/docs/errors).
Schema ErrorEnvelope (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
Send a test event
POST /webhooks/{id}/test
Auth: API key with scope webhooks:write, or access token.
Requires webhooks:write. Queues a signed webhook.test event to this webhook (whatever its events); follow it in GET /webhooks/{id}/deliveries. At most 10 per webhook per hour.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook id. An unknown or malformed id is 404. |
Responses
202 Queued.
Schema WebhookTestResult (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"eventId": "evt_3f2a…",
"deliveryId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d"
} 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 WEBHOOK_STATE_CONFLICT: the webhook is disabled (details.action test).
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
List deliveries
GET /webhooks/{id}/deliveries
Auth: API key with scope webhooks:read or webhooks:write, or access token.
Requires webhooks:read or webhooks:write. Deliveries of this webhook, newest first, with every attempt (status code, latency, error class and the start of the response body). Kept 30 days after they finish.
Credits. Free: no credits.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
id required | path | string | Webhook id. An unknown or malformed id is 404. |
limit | query | integer | 1–100, default 20. Default: 20 |
cursor | query | string | nextCursor of the previous page. |
status | query | WebhookDeliveryStatus |
Responses
200 A page of deliveries.
Schema WebhookDeliveryList (application/json).
Headers: X-Request-Id , RateLimit , RateLimit-Policy
{
"data": [
{
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"eventId": "evt_3f2a…",
"eventType": "generation.succeeded",
"status": "pending",
"attempts": 0,
"nextAttemptAt": "2026-10-21T12:00:00.000Z",
"createdAt": "2026-10-21T12:00:00.000Z",
"finishedAt": "2026-10-21T12:00:00.000Z",
"log": [
{}
]
}
],
"nextCursor": "string"
} 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
Webhook events
Sent as signed POST requests to your webhook URL. See the
webhook endpoints above to subscribe.
generation.succeeded: A generation succeeded
POST to your webhook URL (at least once, unordered). Answer any 2xx within 10 seconds; anything else is retried 7 times over about 23 hours. Verify Storeshot-Signature over the raw body before parsing it.
Headers: storeshot-signature , storeshot-event-id , storeshot-event-type , storeshot-delivery-id , storeshot-delivery-attempt
Payload schema GenerationSucceededEvent.
| Field | Type | Description |
|---|---|---|
idrequired | string | Event id (evt_…), identical on every attempt: deduplicate on it. |
typerequired | string | One of: "generation.succeeded" |
createdrequired | string | RFC 3339 UTC timestamp. |
environmentrequired | ApiKeyEnvironment | |
apiVersionrequired | string | |
datarequired | WebhookGenerationData |
{
"id": "string",
"type": "generation.succeeded",
"created": "2026-10-21T12:00:00.000Z",
"environment": "live",
"apiVersion": "1.8.0",
"data": {
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"status": "queued",
"environment": "live",
"inputs": [
{
"uploadId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"sourceUrl": "string"
}
],
"store": "app_store",
"device": "app_store_1290x2796",
"size": {
"width": 1,
"height": 1
},
"orientation": "portrait",
"app": {
"name": "string",
"description": "string"
},
"caption": "string",
"palette": [
{}
],
"logo": {
"uploadId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d"
},
"metadata": {},
"creditsCharged": 0,
"creditsRefunded": 0,
"result": {
"image": {
"contentType": "image/png",
"width": 1290,
"height": 2796
},
"thumbnail": {
"contentType": "image/webp"
},
"caption": "string",
"palette": []
},
"error": {
"code": "GENERATION_FAILED",
"message": "string"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"startedAt": "2026-10-21T12:00:00.000Z",
"finishedAt": "2026-10-21T12:00:00.000Z",
"deletedAt": "2026-10-21T12:00:00.000Z",
"screenshotSet": {
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"position": 1,
…Shortened; the Markdown version has the full example.
generation.failed: A generation failed or was canceled
POST to your webhook URL (at least once, unordered). Answer any 2xx within 10 seconds; anything else is retried 7 times over about 23 hours. Verify Storeshot-Signature over the raw body before parsing it.
Headers: storeshot-signature , storeshot-event-id , storeshot-event-type , storeshot-delivery-id , storeshot-delivery-attempt
Payload schema GenerationFailedEvent.
| Field | Type | Description |
|---|---|---|
idrequired | string | Event id (evt_…), identical on every attempt: deduplicate on it. |
typerequired | string | One of: "generation.failed" |
createdrequired | string | RFC 3339 UTC timestamp. |
environmentrequired | ApiKeyEnvironment | |
apiVersionrequired | string | |
datarequired | WebhookGenerationData |
{
"id": "string",
"type": "generation.failed",
"created": "2026-10-21T12:00:00.000Z",
"environment": "live",
"apiVersion": "1.8.0",
"data": {
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"status": "queued",
"environment": "live",
"inputs": [
{
"uploadId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"sourceUrl": "string"
}
],
"store": "app_store",
"device": "app_store_1290x2796",
"size": {
"width": 1,
"height": 1
},
"orientation": "portrait",
"app": {
"name": "string",
"description": "string"
},
"caption": "string",
"palette": [
{}
],
"logo": {
"uploadId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d"
},
"metadata": {},
"creditsCharged": 0,
"creditsRefunded": 0,
"result": {
"image": {
"contentType": "image/png",
"width": 1290,
"height": 2796
},
"thumbnail": {
"contentType": "image/webp"
},
"caption": "string",
"palette": []
},
"error": {
"code": "GENERATION_FAILED",
"message": "string"
},
"createdAt": "2026-10-21T12:00:00.000Z",
"startedAt": "2026-10-21T12:00:00.000Z",
"finishedAt": "2026-10-21T12:00:00.000Z",
"deletedAt": "2026-10-21T12:00:00.000Z",
"screenshotSet": {
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"position": 1,
…Shortened; the Markdown version has the full example.
screenshot_set.completed: A screenshot set reached a final status
POST to your webhook URL (at least once, unordered). Answer any 2xx within 10 seconds; anything else is retried 7 times over about 23 hours. Verify Storeshot-Signature over the raw body before parsing it.
Headers: storeshot-signature , storeshot-event-id , storeshot-event-type , storeshot-delivery-id , storeshot-delivery-attempt
Payload schema ScreenshotSetCompletedEvent.
| Field | Type | Description |
|---|---|---|
idrequired | string | Event id (evt_…), identical on every attempt: deduplicate on it. |
typerequired | string | One of: "screenshot_set.completed" |
createdrequired | string | RFC 3339 UTC timestamp. |
environmentrequired | ApiKeyEnvironment | |
apiVersionrequired | string | |
datarequired | WebhookScreenshotSetData |
{
"id": "string",
"type": "screenshot_set.completed",
"created": "2026-10-21T12:00:00.000Z",
"environment": "live",
"apiVersion": "1.8.0",
"data": {
"id": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"status": "queued",
"environment": "live",
"app": {
"name": "string",
"description": "string"
},
"orientation": "portrait",
"palette": [
{}
],
"paletteSource": "given",
"logo": {
"uploadId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d"
},
"metadata": {},
"screens": [
{
"position": 1,
"input": {},
"caption": "string"
}
],
"stores": [
{
"devices": [],
"featureGraphic": {}
}
],
"images": 1,
"counts": {
"queued": 0,
"running": 0,
"succeeded": 0,
"failed": 0,
"canceled": 0
},
"creditsCharged": 0,
"creditsRefunded": 0,
"children": [
{
"position": 1,
"device": "string",
"size": {},
"featureGraphic": true,
"generationId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"attempt": 1,
"error": {}
}
],
"archiveUrl": "/v1/screenshot-sets/5c1e…/archive",
"createdAt": "2026-10-21T12:00:00.000Z",
"updatedAt": "2026-10-21T12:00:00.000Z",
…Shortened; the Markdown version has the full example.
credits.low: The live credit balance fell below the threshold
POST to your webhook URL (at least once, unordered). Answer any 2xx within 10 seconds; anything else is retried 7 times over about 23 hours. Verify Storeshot-Signature over the raw body before parsing it.
Headers: storeshot-signature , storeshot-event-id , storeshot-event-type , storeshot-delivery-id , storeshot-delivery-attempt
Payload schema CreditsLowEvent.
| Field | Type | Description |
|---|---|---|
idrequired | string | Event id (evt_…), identical on every attempt: deduplicate on it. |
typerequired | string | One of: "credits.low" |
createdrequired | string | RFC 3339 UTC timestamp. |
environmentrequired | ApiKeyEnvironment | |
apiVersionrequired | string | |
datarequired | object | |
data.balancesrequired | object | |
data.balances.starterrequired | integer | |
data.balances.subscriptionrequired | integer | |
data.balances.purchasedrequired | integer | |
data.totalrequired | integer | |
data.thresholdrequired | integer |
{
"id": "string",
"type": "credits.low",
"created": "2026-10-21T12:00:00.000Z",
"environment": "live",
"apiVersion": "1.8.0",
"data": {
"balances": {
"starter": 0,
"subscription": 0,
"purchased": 0
},
"total": 0,
"threshold": 0
}
} webhook.test: Test event (POST /webhooks/{id}/test)
POST to your webhook URL (at least once, unordered). Answer any 2xx within 10 seconds; anything else is retried 7 times over about 23 hours. Verify Storeshot-Signature over the raw body before parsing it.
Headers: storeshot-signature , storeshot-event-id , storeshot-event-type , storeshot-delivery-id , storeshot-delivery-attempt
Payload schema WebhookTestEvent.
| Field | Type | Description |
|---|---|---|
idrequired | string | Event id (evt_…), identical on every attempt: deduplicate on it. |
typerequired | string | One of: "webhook.test" |
createdrequired | string | RFC 3339 UTC timestamp. |
environmentrequired | ApiKeyEnvironment | |
apiVersionrequired | string | |
datarequired | object | |
data.webhookIdrequired | string | Format: uuid |
data.messagerequired | string |
{
"id": "string",
"type": "webhook.test",
"created": "2026-10-21T12:00:00.000Z",
"environment": "live",
"apiVersion": "1.8.0",
"data": {
"webhookId": "7d0e1a52-3c4b-4f6e-9a8d-2b1c0f9e8a7d",
"message": "string"
}
}