Skip to content

Batches

Message Batches let you send large volumes of message requests asynchronously at 50% of the normal cost. Results are available within 24 hours. A great fit for bulk processing jobs in Laravel.

Creating a batch

use Anthropic\Laravel\Facades\Anthropic;

$response = Anthropic::batches()->create([
    'requests' => [
        [
            'custom_id' => 'request-1',
            'params' => [
                'model' => 'claude-sonnet-4-6',
                'max_tokens' => 1024,
                'messages' => [
                    ['role' => 'user', 'content' => 'What is the capital of France?'],
                ],
            ],
        ],
        [
            'custom_id' => 'request-2',
            'params' => [
                'model' => 'claude-sonnet-4-6',
                'max_tokens' => 1024,
                'messages' => [
                    ['role' => 'user', 'content' => 'What is the capital of Germany?'],
                ],
            ],
        ],
    ],
]);

$response->id;                        // 'msgbatch_04Rka1yCsMLGPnR7kfPdgR8x'
$response->processingStatus;          // 'in_progress'
$response->requestCounts->processing; // 2
$response->createdAt;                 // '2026-04-14T12:00:00Z'
$response->expiresAt;                 // '2026-04-15T12:00:00Z'

The params object inside each request takes the same parameters you'd pass to Anthropic::messages()->create(). Tool use, thinking, and system messages all work.

Polling with a scheduled command

A good Laravel pattern is to store the batch ID on a model, then poll with a scheduled job:

// Save when creating
$job = BatchJob::create([
    'anthropic_batch_id' => $response->id,
    'status' => $response->processingStatus,
]);

// Poll on a schedule (app/Console/Kernel.php)
$schedule->command('batches:poll')->everyFiveMinutes();
class PollBatchesCommand extends Command
{
    protected $signature = 'batches:poll';

    public function handle(): void
    {
        BatchJob::whereNotIn('status', ['ended', 'canceled'])
            ->each(function (BatchJob $job) {
                $response = Anthropic::batches()->retrieve($job->anthropic_batch_id);

                $job->update(['status' => $response->processingStatus]);

                if ($response->processingStatus === 'ended') {
                    ProcessBatchResultsJob::dispatch($job);
                }
            });
    }
}

Batch processing statuses

Status Meaning
in_progress Batch is being processed
canceling Cancellation requested, finishing in-progress requests
ended All requests completed (check requestCounts for breakdown)

A canceled batch ends up with status ended, not a separate canceled status. The requestCounts breakdown tells you how many individual requests succeeded, errored, were canceled, or expired.

Processing results

Once a batch has ended, stream the results:

class ProcessBatchResultsJob implements ShouldQueue
{
    public function __construct(public BatchJob $job) {}

    public function handle(): void
    {
        $results = Anthropic::batches()->results($this->job->anthropic_batch_id);

        foreach ($results as $individual) {
            if ($individual->result->type === 'succeeded') {
                Answer::create([
                    'request_id' => $individual->customId,
                    'content' => $individual->result->message->content[0]->text,
                ]);
            }

            if ($individual->result->type === 'errored') {
                Log::error('Batch request failed', [
                    'custom_id' => $individual->customId,
                    'error' => $individual->result->error->message,
                ]);
            }
        }
    }
}

Results are streamed as JSONL so you can process thousands of items without loading everything into memory.

Listing, canceling, deleting

// List with pagination
$response = Anthropic::batches()->list(['limit' => 10]);

// Cancel in-progress
Anthropic::batches()->cancel('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

// Delete after completion
Anthropic::batches()->delete('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

For batch limits, pricing, and the full lifecycle, see the Batches page in the PHP docs or the Batch processing guide on the Anthropic docs.

Scroll to top