Submit a batch job
Queues many URLs as one asynchronous job and returns `202` with the job object immediately.
Requires scope: batch
Queues many URLs as one asynchronous job and returns 202 with the job object immediately.
Supply either urls (same settings for every URL) or items (one object per URL, with per-item
overrides), never both. Every /v1/scrape parameter at the top level (except url) is a job-wide
default; an item's own value wins over it, including an explicit false.
Order of work: validate and route every item (a bad item N fails the whole submission with
Item N: in detail), reserve the dearest possible cost of the whole job against the monthly
credit allowance, write the manifest, enqueue. Nothing is charged at submission
(X-Credits-Charged: 0); items are charged individually, only on success, by the worker.
Next step: poll GET /v1/batch/{batchID} (the status_url) until status is
completed, failed or cancelled, then page GET /v1/batch/{batchID}/results.
Results are readable while the job runs, too.
Not idempotent: there is no Idempotency-Key. Resubmitting the same body creates a second job that
is scraped and billed again. If a 202 carries a warning saying items were not all dispatched,
do NOT resubmit — the worker's recovery sweep dispatches them.
Limits: request body 1 MiB (1,048,576 bytes); at most 10,000 items per call; job-level
parameters at most 65,536 bytes serialised; each item's overrides plus external_id at most
8,192 bytes serialised.
Authorization
bearerAuth Authorization: Bearer <key>. Read the key from the SPICRAWL_API_KEY environment
variable; never hard-code or log it. spicrawl_test_… keys can never spend live
credits. Scopes: scrape, batch, sessions (granted by default), browser
and read (granted deliberately). A missing scope is 403 ERR::AUTH::INSUFFICIENT_SCOPE naming the scope.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Body of POST /v1/batch (and of POST /v1/batch/{batchID}/items). Exactly one of urls or items must be non-empty.
Top-level BatchScrapeParams fields are job-wide defaults. A top-level url is rejected with 400 — put targets in
urls or items[].url. Unknown fields are a 400. Must be ≤ 1 MiB; ≤ 10,000 targets.
Response Body
application/json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
application/problem+json
curl -X POST "https://example.com/v1/batch" \ -H "Content-Type: application/json" \ -d '{ "name": "nightly-catalog", "urls": [ "https://example.com/products/1", "https://example.com/products/2" ], "js_render": true, "premium_proxy": true, "proxy_country": "us", "concurrency": 20 }'{ "id": "01J9Z6T3W9E21T5TZARVJRVN5C", "project_id": "01J8X2M4C7Q1H5V9P3R6T8W0YB", "name": "catalog-2026-09-22", "status": "running", "status_url": "/v1/batch/01J9Z6T3W9E21T5TZARVJRVN5C", "results_url": "/v1/batch/01J9Z6T3W9E21T5TZARVJRVN5C/results", "params": { "js_render": true, "proxy_country": "us", "credit_budget_micro": 8000000 }, "total_items": 2, "concurrency": 20, "priority": 100, "max_attempts": 3, "estimated_credits": 8, "estimated_credits_micro": 8000000, "progress": { "total": 2, "completed": 1, "succeeded": 1, "failed": 0, "cancelled": 0, "skipped": 0, "remaining": 1, "percent_complete": 50, "credits_charged": 4, "credits_charged_micro": 4000000, "bytes": 326000 }, "submitted_at": "2026-09-22T06:41:12Z", "started_at": "2026-09-22T06:41:13Z", "results_expire_at": "2026-09-25T06:41:12Z"}