Bulk captures

Up to 1,000 items in one call.

POST /v1/bulk
{
  "endpoint": "take",
  "options": { "format": "png", "viewport_width": 1280 },
  "requests": [
    { "url": "https://example.com/a", "external_identifier": "a" },
    { "url": "https://example.com/b", "external_identifier": "b" }
  ]
}

options are the shared defaults; each item overrides what it needs.

Two rules govern the response:

  • An invalid envelope rejects the whole call. An invalid item rejects only that item — a batch of 900 good URLs is not lost because item 42 has a bad selector.
  • The index → result correspondence is preserved. Internal ordering may be optimised; the response order never changes.

Send "execute": false to validate a batch without queueing anything or spending credits.

Every item passes the same plan checks: it consumes one start from the same per-minute bucket as /take, and one credit on success. An item that hits the bucket fails at its own index with concurrency_limit_reached; the rest of the batch continues. Bulk is not a side door around your plan.

Retrying a batch safely

A large batch is the case most likely to time out on the client side, and a timed-out call has already queued — and will bill — whatever it admitted before dying. Send an Idempotency-Key header to make the retry harmless:

curl -X POST https://api.pagecapture.dev/v1/bulk \
  -H "X-Access-Key: $PAGECAPTURE_KEY" \
  -H "Idempotency-Key: batch-2026-08-02-0001" \
  -H "Content-Type: application/json" \
  -d @batch.json

Resending with the same key never admits new work. If the original finished, you get its exact response back. If it died partway, you get the request_ids that exist, plus "incomplete": true and unresolved — the count whose fate is unknown. Both replies carry Idempotent-Replay: true.

Keys are scoped to your organization. Without the header, nothing changes: every call is a new batch.