BatchJob
The batch job, identical in shape across create, list, get, cancel and close. Poll `status_url` until `status` is terminal (`completed`, `failed`, `cancelled`), then read `results_url` before `results_expire_at`. There is no `credits_held` field: the hold is `estimated_credits`, the spend is `progress.credits_charged`.
Properties
| Name | Type | Description |
|---|---|---|
| id | string | Job id (26-character ULID). Use it in every /v1/batch/{batchID} path. |
| project_id | string | Project the submitting API key belongs to. |
| name | string | The `name` you submitted. Absent when none. |
| status | object | Current lifecycle state. Keep polling while `queued`, `running`, `paused` or `cancelling`; stop at `completed`, `failed` or `cancelled`. |
| open | boolean | Present and true while the job accepts appended items; it will not complete until you close it. Absent means closed. |
| status_url | string | Relative path to poll: /v1/batch/{id}. |
| results_url | string | Relative path of the JSONL results: /v1/batch/{id}/results. |
| params | object | The job-level scrape parameters as stored (your top-level BatchScrapeParams, without `url`), plus two keys the API sets and you cannot — `credit_budget_micro`, the run ceiling the worker enforces, and |
| total_items | integer | Number of items in the job. Fixed at submission unless items are appended to an open job. |
| concurrency | integer | Effective per-job concurrency after clamping. |
| priority | integer | Effective priority. |
| max_attempts | integer | Effective attempts per item. |
| failure_threshold | integer | Failed-item count that aborts the job. Absent when not set. |
| estimated_credits | integer | Credits RESERVED against the monthly allowance at submission — the dearest outcome of every item (whole credits, rounded down). It is a hold, not a charge; credits held for items that fail, are cancel |
| estimated_credits_micro | integer | Same as `estimated_credits` in micro-credits. |
| progress | object | Live item counters and the credits actually charged so far. |
| submitted_at | string | When the job was accepted. |
| started_at | string | When the first item started. Absent until then. |
| finished_at | string | When the job reached a terminal status. Cleared again by batchRetry. |
| cancel_requested_at | string | When a cancel was accepted. The job may still be `cancelling` after this while in-flight items drain. |
| results_expire_at | string | Results deadline: submitted_at + 72 h by default. After it, GET .../results answers 410. Download before this time. |
| error_code | string | Machine code of a job-level failure (for example the job was aborted). Absent otherwise. |
| error_message | string | Human-readable job-level failure reason. |
| warnings | array | Decisions made on your behalf at submission — a clamped `concurrency`, or items not yet handed to the queue (do NOT resubmit in that case). Present only on the create response. |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/spicrawl-com/json-schema/spicrawl-com-batch-job-schema.json",
"title": "BatchJob",
"description": "The batch job, identical in shape across create, list, get, cancel and close. Poll `status_url` until `status` is\nterminal (`completed`, `failed`, `cancelled`), then read `results_url` before `results_expire_at`.\nThere is no `credits_held` field: the hold is `estimated_credits`, the spend is `progress.credits_charged`.\n",
"x-generated": "2026-10-31",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/spicrawl-com-openapi.yaml#/components/schemas/BatchJob",
"type": "object",
"required": [
"id",
"project_id",
"status",
"status_url",
"results_url",
"params",
"total_items",
"concurrency",
"priority",
"max_attempts",
"estimated_credits",
"estimated_credits_micro",
"progress",
"submitted_at"
],
"properties": {
"id": {
"type": "string",
"description": "Job id (26-character ULID). Use it in every /v1/batch/{batchID} path."
},
"project_id": {
"type": "string",
"description": "Project the submitting API key belongs to."
},
"name": {
"type": "string",
"description": "The `name` you submitted. Absent when none."
},
"status": {
"$ref": "#/$defs/BatchJobStatus",
"description": "Current lifecycle state. Keep polling while `queued`, `running`, `paused` or `cancelling`; stop at `completed`, `failed` or `cancelled`."
},
"open": {
"type": "boolean",
"description": "Present and true while the job accepts appended items; it will not complete until you close it. Absent means closed."
},
"status_url": {
"type": "string",
"description": "Relative path to poll: /v1/batch/{id}."
},
"results_url": {
"type": "string",
"description": "Relative path of the JSONL results: /v1/batch/{id}/results."
},
"params": {
"type": "object",
"additionalProperties": true,
"description": "The job-level scrape parameters as stored (your top-level BatchScrapeParams, without `url`), plus two keys the API sets and you cannot — `credit_budget_micro`, the run ceiling the worker enforces, and `default_proxy_tier` (`direct` or `datacenter`), the exit an item that sets no `proxy`, `premium_proxy`, `proxy_country` or `sticky_key` takes, decided at submission the way `/v1/scrape` decides it. Always present, possibly only those two."
},
"total_items": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Number of items in the job. Fixed at submission unless items are appended to an open job."
},
"concurrency": {
"type": "integer",
"minimum": 1,
"maximum": 50,
"description": "Effective per-job concurrency after clamping."
},
"priority": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Effective priority."
},
"max_attempts": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"description": "Effective attempts per item."
},
"failure_threshold": {
"type": "integer",
"format": "int64",
"minimum": 1,
"description": "Failed-item count that aborts the job. Absent when not set."
},
"estimated_credits": {
"type": "integer",
"minimum": 0,
"description": "Credits RESERVED against the monthly allowance at submission — the dearest outcome of every item (whole credits, rounded down). It is a hold, not a charge; credits held for items that fail, are cancelled or skipped are returned to the monthly allowance within about a minute of the item finishing, by a background settler. Succeeded items keep their charge. Not increased by appends. Appended items are reserved when they are added, and the append's own total is its `X-Request-Cost`. Retrying failed items (`POST /v1/batch/{id}/retry`) holds their price again first and is refused with 402 if the allowance cannot cover it."
},
"estimated_credits_micro": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Same as `estimated_credits` in micro-credits."
},
"progress": {
"$ref": "#/$defs/BatchJobProgress",
"description": "Live item counters and the credits actually charged so far."
},
"submitted_at": {
"type": "string",
"format": "date-time",
"description": "When the job was accepted."
},
"started_at": {
"type": "string",
"format": "date-time",
"description": "When the first item started. Absent until then."
},
"finished_at": {
"type": "string",
"format": "date-time",
"description": "When the job reached a terminal status. Cleared again by batchRetry."
},
"cancel_requested_at": {
"type": "string",
"format": "date-time",
"description": "When a cancel was accepted. The job may still be `cancelling` after this while in-flight items drain."
},
"results_expire_at": {
"type": "string",
"format": "date-time",
"description": "Results deadline: submitted_at + 72 h by default. After it, GET .../results answers 410. Download before this time."
},
"error_code": {
"type": "string",
"description": "Machine code of a job-level failure (for example the job was aborted). Absent otherwise."
},
"error_message": {
"type": "string",
"description": "Human-readable job-level failure reason."
},
"warnings": {
"type": "array",
"items": {
"type": "string"
},
"description": "Decisions made on your behalf at submission — a clamped `concurrency`, or items not yet handed to the queue (do NOT resubmit in that case). Present only on the create response."
}
},
"$defs": {
"BatchJobProgress": {
"type": "object",
"description": "Live counters for the job, read from sharded counters. `completed` = succeeded + failed + cancelled + skipped; `remaining` = total − completed.",
"required": [
"total",
"completed",
"succeeded",
"failed",
"cancelled",
"skipped",
"remaining",
"percent_complete",
"credits_charged",
"credits_charged_micro",
"bytes"
],
"properties": {
"total": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items in the job (same as `total_items`). Grows when items are appended to an open job."
},
"completed": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items in any terminal status."
},
"succeeded": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items that succeeded. Only these are charged."
},
"failed": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items that failed after all attempts. Re-run them with POST /v1/batch/{batchID}/retry."
},
"cancelled": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items not run because the job was cancelled."
},
"skipped": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items the worker skipped (for example after `failure_threshold` or `credit_budget` stopped the run)."
},
"remaining": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Items not yet finished."
},
"percent_complete": {
"type": "number",
"minimum": 0,
"maximum": 100,
"description": "completed / total × 100."
},
"credits_charged": {
"type": "integer",
"minimum": 0,
"description": "Credits actually charged so far, whole credits rounded down. Sum over succeeded items only. This is the real spend; compare with the job's `estimated_credits` (the hold)."
},
"credits_charged_micro": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Same as `credits_charged` in micro-credits (1 credit = 1,000,000). Use this for exact accounting."
},
"bytes": {
"type": "integer",
"format": "int64",
"minimum": 0,
"description": "Total response bytes of finished items."
}
}
},
"BatchJobStatus": {
"type": "string",
"enum": [
"queued",
"running",
"paused",
"cancelling",
"completed",
"failed",
"cancelled"
],
"description": "Job lifecycle. `queued` → `running` → `completed` | `failed`; cancel moves a live job to `cancelling`, then the worker\nmoves it to `cancelled` once in-flight items drain. `paused` is an operator state (no public endpoint pauses).\nTerminal: `completed`, `failed`, `cancelled` — stop polling. A terminal job returns to `queued` after batchRetry.\n"
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/spicrawl-com-batch-job"
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.