Cancel a bulk job

Cancels an in-flight bulk job: drains its still-queued (pending) child jobs and refunds the quota held for exactly those drained children. Children already completed, failed, or in progress are untouched and keep their charge. Idempotent — cancelling an already-terminal job (completed, failed, or cancelled) is a no-op that returns 200 with the job's real, unchanged status and refunds nothing.

For AI agents: https://bytekit.com/llms.txt — every docs page is available as markdown by appending .md

DELETE
/v1/bulk/{id}

Authorization

AuthorizationRequiredBearer <token>

API key. Manage keys from the dashboard at app.bytekit.com.

In: header

Path Parameters

idRequiredstring
Pattern: "^bulk_"
curl -X DELETE https://api.bytekit.com/v1/bulk/{id} \
  -H "Authorization: Bearer sk_live_your_api_key_here"

Bulk job after the cancel attempt. status is cancelled when the job was in flight, or its real terminal status when it had already finished.

{
  "id": "bulk_01j9abc123",
  "status": "processing",
  "total": 0,
  "completed": 0,
  "failed": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "completed_at": "2019-08-24T14:15:22Z",
  "total_credits_charged": 0,
  "total_billed_bytes": 0,
  "estimated_credits": 0,
  "webhook_url": "string"
}

GET /v1/bulk/{id}Get bulk job status

Returns the job envelope. Items are listed by `GET /v1/bulk/{id}/screenshots`. **Cancelled by the platform.** When the account can no longer spend (its bandwidth balance is exhausted, or the account is deleted) while items are still pending, ByteKit cancels the job itself. It then reads `status: cancelled` even though you never called `DELETE /v1/bulk/{id}`, and the cancellation sends no webhook. **Job ids from other create routes.** The job is looked up by account only, so the id of a job created by `POST /v1/scrape/bulk` or `POST /v1/fetch/bulk` is found here too, not a `404`, with that job's envelope. An id from another account answers `404`.

GET /v1/bulk/{id}/screenshotsList bulk job items

Returns the bulk job's items, discriminated by `type`. **Downloading item artifacts.** For a `completed` item with a storage key, `image_url` (`type: screenshot`) and both `content_url` and `markdown_url` (`type: scrape`) are **pre-signed** URLs, minted fresh on every read of this endpoint and valid for **600 seconds (10 minutes)** — the same signing lifetime as `content_url` on `GET /v1/fetch/bulk/{id}`. Download inside that window, or re-poll this endpoint for a fresh signature. **When no signature is minted.** Three cases mint none: an item that is not `completed`, a `completed` item with no storage key, and a `completed` item whose object could not be signed — during an object-storage outage, for instance. In all three the item's stored value is returned unchanged: `null` while nothing has been stored, and otherwise a **private, unsigned** object-storage URL that answers `401`. These fields are neither nulled nor flagged in that case, so treat an artifact URL as usable only once you have downloaded it, and re-poll for a fresh signature otherwise. `artifact_warnings` and its `artifact_unavailable` code describe the sibling `artifacts` object on `type: scrape` items only — they say nothing about `image_url`, `content_url`, or `markdown_url`.