/v1/screenshot-batchesQueue a screenshot batch
Atomically reserves credits and creates 1–10 independent queued captures with shared options, including fixed A4 PDF. Duplicate URLs remain separate ordered items. PDF has a two-credit base and follows the same incompatible-field and required-brand-removal rules as asynchronous single capture. Each item uses the ordinary capture queue, retry, retention, and settlement lifecycle. Webhooks, customer-storage delivery, templates, schedules, and per-item overrides are not supported. This action also has a five-requests-per-minute limit.
operationId: createScreenshotBatch
Example request
curl -X POST "https://api.capturewell.app/v1/screenshot-batches" \
-H "Authorization: Bearer $CAPTUREWELL_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"urls": [
"https://example.com",
"https://example.org"
],
"format": "webp",
"full_page": true,
"preset": "desktop"
}'Request body
application/json required
| Field | Type | Requirement | Description |
|---|---|---|---|
| urls | array<string> | Required | Public HTTP or HTTPS targets in preserved request order. Duplicate URLs create separate captures.items: 1–10 |
| format | png | jpeg | webp | avif | pdf | Optional | No descriptiondefault: "png" |
| quality | integer | Optional | Shared JPEG, WebP, or AVIF quality. Omit for PDF.range: 1–100 |
| full_page | boolean | Optional | No descriptiondefault: false |
| preset | desktop | desktop_hd | laptop | tablet | tablet_landscape | iphone_16 | pixel_10 | social_card | open_graph | Optional | No descriptiondefault: "desktop" |
| viewport | RequestedViewport | Optional | No description |
| viewport.width | integer | Optional | No descriptionrange: 320–3840 |
| viewport.height | integer | Optional | No descriptionrange: 240–2160 |
| device_scale_factor | number | Optional | No descriptionrange: 1–3 |
| delay_ms | integer | Optional | No descriptiondefault: 0 · range: 0–10000 |
| timeout_ms | integer | Optional | No descriptiondefault: 30000 · range: 1000–60000 |
| wait_until | load | domcontentloaded | networkidle0 | networkidle2 | Optional | No descriptiondefault: "networkidle2" |
| wait_for_selector | string | null | Optional | No descriptiondefault: null · length: 0–500 |
| dark_mode | boolean | Optional | No descriptiondefault: false |
| reduced_motion | boolean | Optional | No descriptiondefault: true |
| remove_branding | boolean | Optional | For PDF under required Capturewell branding, this must be explicitly true and adds the configured removal credit up front.default: false |
| watermark_id | string | null | Optional | Owned watermark public ULID shared by every item. Requires remove_branding and enabled watermarking. Omit for PDF. |
| recipe_id | string | null | Optional | Owned active recipe public ULID shared by every item. |
{
"urls": [
"https://example.com",
"https://example.org"
],
"format": "webp",
"full_page": true,
"preset": "desktop"
}Responses
202The complete batch was created and queued.
application/json
| Field | Type | Requirement | Description |
|---|---|---|---|
| id | string | Required | No description |
| status | queued | processing | completed | completed_with_failures | failed | Required | No description |
| total | integer | Required | No descriptionrange: 1–10 |
| created_at | string | null | Required | No descriptionformat: date-time |
| counts | CaptureBatchCounts | Required | No description |
| counts.queued | integer | Required | No descriptionrange: 0–∞ |
| counts.processing | integer | Required | No descriptionrange: 0–∞ |
| counts.completed | integer | Required | No descriptionrange: 0–∞ |
| counts.failed | integer | Required | No descriptionrange: 0–∞ |
| counts.deleted | integer | Required | No descriptionrange: 0–∞ |
| credits_reserved | integer | Required | No descriptionrange: 0–∞ |
| credits_used | integer | Required | No descriptionrange: 0–∞ |
| captures | array<Capture | DeletedBatchCapture> | Required | No descriptionitems: 1–10 |
{
"id": "01J00000000000000000000010",
"status": "queued",
"total": 1,
"created_at": "2026-07-21T12:00:00Z",
"counts": {
"queued": 1,
"processing": 0,
"completed": 0,
"failed": 0,
"deleted": 0
},
"credits_reserved": 1,
"credits_used": 0,
"captures": [
{
"id": "01J00000000000000000000011",
"status": "queued",
"source": "api",
"target_url": "https://example.com",
"options": {
"url": "https://example.com",
"format": "png",
"quality": null,
"full_page": false,
"preset": "desktop",
"viewport": {
"width": 1440,
"height": 900,
"device_scale_factor": 1,
"mobile": false
},
"delay_ms": 0,
"timeout_ms": 30000,
"wait_until": "networkidle2",
"wait_for_selector": null,
"dark_mode": false,
"reduced_motion": true,
"remove_branding": false
},
"file_url": null,
"image_url": null,
"download_url": null,
"expires_at": "2026-07-22T12:00:00Z",
"credits_used": 1,
"watermarked": false,
"watermark_removal": {
"eligible": false,
"credits": 1,
"removed_at": null
},
"recipe": null,
"webhook": null,
"external_delivery": null,
"batch_id": "01J00000000000000000000010",
"batch_position": 0,
"created_at": "2026-07-21T12:00:00Z",
"metadata": null,
"error": null
}
]
}401The Bearer key is missing, malformed, revoked, or unknown.
application/json
| Field | Type | Requirement | Description |
|---|---|---|---|
| error | ErrorDetail | Required | No description |
| error.code | string | Required | Stable error identifier. Renderer error codes are extensible strings rather than a closed enum. Known examples include navigation_failed, renderer_unavailable, watermark_unavailable, recipe_not_configured, recipe_planning_failed, recipe_action_not_found, recipe_action_rejected, and recipe_action_limit. |
| error.message | string | Required | No description |
| error.retryable | boolean | Optional | When present, retry automatically only when true. |
{
"error": {
"code": "unauthenticated",
"message": "A valid API key is required."
}
}422Laravel validation failed. Do not retry unchanged input.
application/json
| Field | Type | Requirement | Description |
|---|---|---|---|
| message | string | Required | Summary of the first validation error and any additional error count. |
| errors | object | Required | Field names map to one or more validation messages. Nested keys use dot notation. |
{
"message": "The url field is required.",
"errors": {
"url": [
"The url field is required."
]
}
}429Either an applicable request limit was exceeded or the account lacks enough credits. Authenticated v1 operations default to 60 requests per minute; specific actions may document a lower additional limit. A quota_exceeded response does not include Retry-After and is not rescued synchronously by auto recharge; retry only after the balance has actually increased.
| Header | Type | Example | Description |
|---|---|---|---|
| X-RateLimit-Limit | integer | 60 | Maximum requests in the current window. |
| X-RateLimit-Remaining | integer | 37 | Requests remaining in the current window. |
| Retry-After | integer | 42 | Present only when the request limiter, rather than the credit quota, caused the response. |
| X-RateLimit-Reset | integer | 1784203242 | Present when the request limiter supplies a reset timestamp. |
application/json
{
"message": "Too Many Attempts."
}503The batch was committed but one or more ordinary render jobs could not be dispatched immediately. The response is retryable for status retrieval; queued-capture recovery dispatches stale items automatically. Do not repeat creation unless a second batch is intended.
application/json
| Field | Type | Requirement | Description |
|---|---|---|---|
| batch_id | string | Required | No description |
| error | object | Required | No description |
| error.code | string | Required | No description |
| error.message | string | Required | No description |
| error.retryable | boolean | Required | No description |
{
"batch_id": "01J00000000000000000000010",
"error": {
"code": "batch_dispatch_deferred",
"message": "The batch was created and its queued captures will be retried automatically.",
"retryable": true
}
}