---
title: "Create a batch"
method: POST
path: "/batches"
tags: ["Batches"]
---

# Create a batch

`POST /batches`

Create a batch of requests to run asynchronously. Each request is dispatched to its target route and results are made available for download when the batch completes.

## Headers

- `Exa-Beta` 'batches-2026-06-06', required — Required beta token for the Batch API.

## Request body

- CreateBatchRequest
  - `requests` BatchRequestItem[], required — The requests to enqueue. Each `customId` must be unique within the batch.
    - `customId` string, required — Your unique handle for this request; keys the result and must be unique in the batch.
    - `method` 'POST', required — HTTP method of the batched request. POST-only in v1.
    - `url` '/search' | '/agent/runs', required — Target API route for the request. One of `/search` or `/agent/runs` in v1.
    - `body` object, required — Request body for the target route. Must be a JSON object; `stream: true` is not allowed.
  - `metadata` object — Caller-provided metadata stored with the batch.

## Response `200`

OK

- Batch
  - `id` string, required — Batch ID. New batch IDs are returned with the `batch_` prefix.
  - `object` 'batch', required — The object type, always `batch`.
  - `status` 'in_progress' | 'completed' | 'cancelling' | 'cancelled' | 'expired', required — Lifecycle status of the batch.
  - `requestCounts` BatchRequestCounts, required
    - `total` integer, required — Total requests in the batch.
    - `completed` integer, required — Requests that have completed successfully.
    - `failed` integer, required — Requests that have failed.
  - `createdAt` string, date-time, required — When the batch was created.
  - `expiresAt` string, date-time, nullable, required — When the batch expires, or `null` if it does not expire.
  - `endedAt` string, date-time, nullable, required — When the batch reached a terminal status, or `null` while it is still running.
  - `resultsUrl` string, nullable, required — Short-lived presigned download URL for the batch results file (JSONL), or `null` until the batch completes. This is a direct object-store download link, not an API route; fetch it as-is and re-fetch the batch to mint a fresh URL once it expires.
  - `metadata` object, required — Caller-provided key-value metadata for your own tracking.

## Other responses

- `400` — The request body or query parameters failed validation.
- `401` — The API key is missing or invalid.
- `500` — An unexpected error occurred while processing the request.

## Changes

- **2026-08-27** `67abccbd77b6` — 1 warning, 2 info
  - deleted the `header` request parameter `Exa-Version`
  - added the non-success response with the status `400`
  - added the non-success response with the status `500`
- **2026-08-26** `bcc51991b48a` — 1 info
  - added the new optional `header` request parameter `Exa-Version`
- **2026-08-25** `659cf16a7325` — 1 info
  - added the non-success response with the status `401`
- **2026-08-24** `cebbdd9640af` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/exa/apis/exa-public-api/changes/batches/post.md)

---

[API](https://skmtc.dev/exa/apis/exa-public-api.md) · [All operations](https://skmtc.dev/exa/apis/exa-public-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/exa/exa-public-api/revisions/67abccbd77b6/schema)
