---
title: "Queue up to 100 requests for one endpoint at half price. Each request becomes one batch job"
method: POST
path: "/v1/batches"
---

# Queue up to 100 requests for one endpoint at half price. Each request becomes one batch job

`POST /v1/batches`

## Request

- Base URL: `https://api.serpkite.com`
- URL: `https://api.serpkite.com/v1/batches`
- Auth: HTTP bearer

Credits for the whole batch are reserved together: if the balance, spend cap, key limit or
free daily cap can't cover every valid request, none is queued and each gets the error
(invalid requests get their own 400 entry either way). Each job is settled and refunded on
its own once it runs.

**Retries.** Send an `Idempotency-Key` to make the call safe to retry: for 24 hours a
repeat with the same key and the same body returns the first response (with
`Idempotent-Replayed: true`) without queueing or billing again. The same key with a
different body is rejected with 422 `idempotency_key_reused`; a repeat while the first
call is still running gets 409.

**Webhooks.** Every delivery is a `POST` with `X-SerpKite-Event: batch.completed`,
`X-SerpKite-Delivery` (the job id), `X-SerpKite-Timestamp` (Unix seconds) and
`X-SerpKite-Signature: v1=<hex HMAC-SHA256(secret, "<timestamp>.<raw body>")>`. Deliveries
are always signed; the account's secret is created with its first webhook and revealed by
rotating it (dashboard Settings → Webhooks). Verify by recomputing the HMAC over the raw
body, comparing in constant time, and rejecting timestamps older than 5 minutes. The SDKs
ship `verifyWebhook` / `verify_webhook` / `VerifyWebhook`.

## Headers

- `Idempotency-Key` string

## Request body

- BatchCreateRequest
  - `endpoint` 'search' | 'images' | 'videos' | 'news' | 'maps' | 'places' | 'reviews' | 'shopping' | 'scholar' | 'patents' | 'autocomplete' | 'webpage', required
  - `requests` object[], required: Request bodies for `endpoint` (same fields as the realtime endpoint)
  - `webhook_url` string, uri: POSTed each job's result, always signed with X-SerpKite-Signature (v1=hex HMAC-SHA256 of `<timestamp>.<body>` with the account webhook secret; see createBatches). Defaults to the account webhook

## Response `202`

Queued. One entry per request, in order; an entry is a batch job or an error object

- BatchCreateResponse
  - `batches` union[], required
    - union
      - Batch
        - `id` string, uuid, required
        - `status` 'queued' | 'running' | 'done' | 'failed', required
        - `endpoint` string, required
        - `created_at` string, date-time, required
        - `completed_at` string, date-time, nullable
        - `credits_used` number
        - `poll_url` string, required
        - `webhook_url` string, nullable
        - `webhook_status` 'pending' | 'delivered' | 'failed' | 'null', nullable
        - `error` object, nullable
          - `code` string
          - `message` string
        - `result` object, nullable: Present when done; kept 24h. The endpoint's response body, or {markdown, meta} for format=markdown jobs
      - Error
        - `error` object, required
          - `code` string, required: 403: spend_cap_reached, key_limit_reached, forbidden. 409/422: idempotency_key_reused. 429: rate_limited, daily_limit_reached. 503: upstream_error, upstream_blocked, upstream_timeout, unavailable (the API never sends 502 or 504)
          - `message` string, required
          - `request_id` string

## Other responses

- `400`: Error
- `401`: Error
- `402`: Error
- `403`: Error
- `409`: Error
- `422`: Error
- `429`: Error
- `503`: Temporarily unavailable, not billed, safe to retry after `Retry-After`. Codes: `upstream_error` (the upstream page couldn't be fetched or parsed), `upstream_blocked` (the upstream is rate limiting us), `upstream_timeout` (the search took too long), `unavailable` (endpoint or dependency down). The API never sends 502 or 504.

---

[API](https://skmtc.dev/serpkite/apis/serpkite-serp-api.md) · [All operations](https://skmtc.dev/serpkite/apis/serpkite-serp-api/llms.txt) · [OpenAPI document](https://skmtc.dev/serpkite/apis/serpkite-serp-api/revisions/f2c6dd05cfc5?raw)
