PHPackages                             mozex/anthropic-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. mozex/anthropic-php

ActiveLibrary[API Development](/categories/api)

mozex/anthropic-php
===================

Anthropic PHP is a supercharged community-maintained PHP API client that allows you to interact with Anthropic API.

1.3.3(2mo ago)46365.1k—7.3%910MITPHPPHP ^8.2.0CI passing

Since May 1Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/mozex/anthropic-php)[ Packagist](https://packagist.org/packages/mozex/anthropic-php)[ GitHub Sponsors](https://github.com/mozex)[ RSS](/packages/mozex-anthropic-php/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (34)Versions (18)Used By (10)

[![Latest Version on Packagist](https://camo.githubusercontent.com/7c20574b98c18a7274d70743af806a61ef2b97b704d3577a983e7d650a07c3af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6f7a65782f616e7468726f7069632d7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mozex/anthropic-php)[![GitHub Tests Workflow Status](https://camo.githubusercontent.com/1d751d9dd2877ee9791f4053fa959bee88631c4426c83078786d0575eb9154c8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6f7a65782f616e7468726f7069632d7068702f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/mozex/anthropic-php/actions/workflows/tests.yml)[![License](https://camo.githubusercontent.com/5b2af10b66fc8e0cc1fdae23843040eb320c10bbd8bae1f90e5757f6fd3108b9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6f7a65782f616e7468726f7069632d7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mozex/anthropic-php)[![Total Downloads](https://camo.githubusercontent.com/35741fe3b5b17c0d3dc92b0ce8a5448c57025ca190a66ca619d87374182a0b64/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d6f7a65782f616e7468726f7069632d7068702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/mozex/anthropic-php)

---

**Anthropic PHP** is a community-maintained PHP API client that allows you to interact with the [Anthropic API](https://docs.anthropic.com/claude/docs/intro-to-claude).

> **Note:** If you want to use the **Anthropic PHP** in Laravel, take a look at the [mozex/anthropic-laravel](https://github.com/mozex/anthropic-laravel) repository.

Table of Contents
-----------------

[](#table-of-contents)

- [Support This Project](#support-this-project)
- [Get Started](#get-started)
- [Usage](#usage)
    - [Messages Resource](#messages-resource)
    - [Models Resource](#models-resource)
    - [Message Batches Resource](#message-batches-resource)
    - [Completions Resource (Legacy)](#completions-resource-legacy)
- [Meta Information](#meta-information)
- [Error Handling](#error-handling)
- [Troubleshooting](#troubleshooting)
- [Testing](#testing)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [Security Vulnerabilities](#security-vulnerabilities)
- [Credits](#credits)
- [License](#license)

Support This Project
--------------------

[](#support-this-project)

I maintain this package along with [several other open-source PHP packages](https://github.com/mozex?tab=repositories&q=&type=source) used by thousands of developers every day.

If my packages save you time or help your business, consider [**sponsoring my work on GitHub Sponsors**](https://github.com/sponsors/mozex). Your support lets me keep these packages updated, respond to issues quickly, and ship new features.

Business sponsors get logo placement in package READMEs. [**See sponsorship tiers →**](https://github.com/sponsors/mozex)

Get Started
-----------

[](#get-started)

> **Requires [PHP 8.2+](https://php.net/releases/)**

First, install Anthropic via the [Composer](https://getcomposer.org/) package manager:

```
composer require mozex/anthropic-php
```

Ensure that the `php-http/discovery` composer plugin is allowed to run or install a client manually if your project does not already have a PSR-18 client integrated.

```
composer require guzzlehttp/guzzle
```

Then, interact with Anthropic's API:

```
$yourApiKey = getenv('YOUR_API_KEY');
$client = Anthropic::client($yourApiKey);

$result = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello!'],
    ],
]);

echo $result->content[0]->text; // Hello! How can I assist you today?

```

If necessary, it is possible to configure and create a separate client.

```
$yourApiKey = getenv('YOUR_API_KEY');

$client = Anthropic::factory()
    ->withApiKey($yourApiKey)
    ->withBaseUri('anthropic.example.com/v1') // default: api.anthropic.com/v1
    ->withHttpClient($httpClient = new \GuzzleHttp\Client([])) // default: HTTP client found using PSR-18 HTTP Client Discovery
    ->withHttpHeader('X-My-Header', 'foo')
    ->withQueryParam('my-param', 'bar')
    ->withStreamHandler(fn (RequestInterface $request): ResponseInterface => $httpClient->send($request, [
        'stream' => true // Allows to provide a custom stream handler for the http client.
    ]))
    ->make();
```

Usage
-----

[](#usage)

### `Messages` Resource

[](#messages-resource)

#### `create`

[](#create)

Creates a completion for structured list of input messages.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello, world'],
    ],
]);

$response->id; // 'msg_01BSy0WCV7QR2adFBauynAX7'
$response->type; // 'message'
$response->role; // 'assistant'
$response->model; // 'claude-sonnet-4-6'
$response->stop_sequence; // null
$response->stop_reason; // 'end_turn'

foreach ($response->content as $result) {
    $result->type; // 'text'
    $result->text; // 'Hello! It's nice to meet you. How can I assist you today?'
}

$response->usage->inputTokens; // 10,
$response->usage->outputTokens; // 19,
$response->usage->cacheCreationInputTokens; // 0,
$response->usage->cacheReadInputTokens; // 0,
$response->usage->cacheCreation; // null or CreateResponseUsageCacheCreation
$response->usage->cacheCreation?->ephemeral5mInputTokens; // 456
$response->usage->cacheCreation?->ephemeral1hInputTokens; // 100
$response->usage->serviceTier; // 'standard', 'priority', 'batch', or null
$response->usage->serverToolUse; // null or CreateResponseUsageServerToolUse
$response->usage->serverToolUse?->webSearchRequests; // 3

$response->toArray(); // ['id' => 'msg_01BSy0WCV7QR2adFBauynAX7', ...]
```

Creates a completion for the structured list of input messages with a tool call.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'What is the weather like in San Francisco?'],
    ],
    'tools' => [
        [
            'name' => 'get_weather',
            'description' => 'Get the current weather in a given location',
            'input_schema' => [
                'type' => 'object',
                'properties' => [
                    'location' => [
                        'type' => 'string',
                        'description' => 'The city and state, e.g. San Francisco, CA'
                    ],
                    'unit' => [
                        'type' => 'string',
                        'enum' => ['celsius', 'fahrenheit'],
                        'description' => 'The unit of temperature, either \"celsius\" or \"fahrenheit\"'
                    ]
                ],
                'required' => ['location']
            ]
        ]
    ]
]);

$response->id; // 'msg_01BSy0WCV7QR2adFBauynAX7'
$response->type; // 'message'
$response->role; // 'assistant'
$response->model; // 'claude-sonnet-4-6'
$response->stop_sequence; // null
$response->stop_reason; // 'tool_use'

$response->content[0]->type; // 'text'
$response->content[0]->text; // 'I'll help you check the current weather in San Francisco. I'll use the get_weather function, assuming San Francisco, CA as the location.'

$response->content[1]->type; // 'tool_use'
$response->content[1]->id; // 'toolu_01RnYGkgJusAzXvcySfZ2Dq7'
$response->content[1]->name; // 'get_weather'
$response->content[1]->input['location']; // 'San Francisco, CA'
$response->content[1]->input['unit']; // 'fahrenheit'

$response->usage->inputTokens; // 448,
$response->usage->outputTokens; // 87,
$response->usage->cacheCreationInputTokens; // 0,
$response->usage->cacheReadInputTokens; // 0,

$response->toArray(); // ['id' => 'msg_01BSy0WCV7QR2adFBauynAX7', ...]
```

Creates a completion with adaptive thinking. This is the recommended approach for Claude Opus 4.6 and Sonnet 4.6, where the model decides when and how much to think based on the request complexity.

```
$response = $client->messages()->create([
    'model' => 'claude-opus-4-6',
    'max_tokens' => 16000,
    'thinking' => [
        'type' => 'adaptive',
    ],
    'messages' => [
        ['role' => 'user', 'content' => 'Explain why the sum of two even numbers is always even.'],
    ],
]);

foreach ($response->content as $block) {
    $block->type; // 'thinking', 'redacted_thinking', or 'text'

    if ($block->type === 'thinking') {
        $block->thinking; // 'Let me analyze this step by step...'
        $block->signature; // 'WaUjzkypQ2mUEVM36O2TxuC06KN8xyfbJwyem...'
    }

    if ($block->type === 'redacted_thinking') {
        $block->data; // 'EmwKAhgBEgy3va3pzix/LafPsn4a'
    }

    if ($block->type === 'text') {
        $block->text; // 'Based on my analysis...'
    }
}
```

Use the `display` option to control how thinking content appears in responses. With `'summarized'` (the default), thinking blocks contain a summary of the model's reasoning. With `'omitted'`, the `thinking` field is empty but the `signature` is still present for multi-turn continuity.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 16000,
    'thinking' => [
        'type' => 'adaptive',
        'display' => 'omitted',
    ],
    'messages' => [
        ['role' => 'user', 'content' => 'What is 27 * 453?'],
    ],
]);

$response->content[0]->type; // 'thinking'
$response->content[0]->thinking; // '' (empty when omitted)
$response->content[0]->signature; // 'EosnCkYICxIMMb3LzNrMu...' (always present)
$response->content[1]->text; // 'The answer is 12,231.'
```

Use `output_config.effort` to guide how much the model thinks. Accepts `'max'` (Opus 4.6 only), `'high'` (default), `'medium'`, or `'low'`. With lower effort, the model may skip thinking entirely for simple queries.

```
$response = $client->messages()->create([
    'model' => 'claude-opus-4-6',
    'max_tokens' => 16000,
    'thinking' => [
        'type' => 'adaptive',
    ],
    'output_config' => [
        'effort' => 'medium',
    ],
    'messages' => [
        ['role' => 'user', 'content' => 'What is the capital of France?'],
    ],
]);
```

For older models (Claude Sonnet 3.7, Opus 4.5, Sonnet 4.5), use `budget_tokens` instead of adaptive thinking.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-5',
    'max_tokens' => 16000,
    'thinking' => [
        'type' => 'enabled',
        'budget_tokens' => 10000,
    ],
    'messages' => [
        ['role' => 'user', 'content' => 'Are there an infinite number of prime numbers such that n mod 4 == 3?'],
    ],
]);
```

Creates a completion with web search. Claude searches the web, and the response contains `server_tool_use`, `web_search_tool_result`, and `text` blocks with citations back to the sources.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'tools' => [['type' => 'web_search_20250305', 'name' => 'web_search']],
    'messages' => [
        ['role' => 'user', 'content' => 'When was Claude Shannon born?'],
    ],
]);

// The search query Claude chose
$response->content[0]->type; // 'server_tool_use'
$response->content[0]->id; // 'srvtoolu_01WYG3ziw53XMcoyKL4XcZmE'
$response->content[0]->name; // 'web_search'
$response->content[0]->input; // ['query' => 'claude shannon birth date']

// Search results (linked back to the server_tool_use by tool_use_id)
$response->content[1]->type; // 'web_search_tool_result'
$response->content[1]->tool_use_id; // 'srvtoolu_01WYG3ziw53XMcoyKL4XcZmE'
$response->content[1]->content[0]['title']; // 'Claude Shannon - Wikipedia'
$response->content[1]->content[0]['url']; // 'https://en.wikipedia.org/wiki/Claude_Shannon'

// Claude's answer with citations to sources
$response->content[2]->type; // 'text'
$response->content[2]->text; // 'Claude Shannon was born on April 30, 1916...'
$response->content[2]->citations[0]['type']; // 'web_search_result_location'
$response->content[2]->citations[0]['title']; // 'Claude Shannon - Wikipedia'
$response->content[2]->citations[0]['url']; // 'https://en.wikipedia.org/wiki/Claude_Shannon'
$response->content[2]->citations[0]['cited_text']; // 'Claude Elwood Shannon (April 30, 1916 – ...'

$response->usage->serverToolUse?->webSearchRequests; // 1
```

Creates a completion with code execution. Claude runs code in a sandboxed container and returns the output. The response may include `bash_code_execution_tool_result` and `text_editor_code_execution_tool_result` blocks depending on which operations Claude performs.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 4096,
    'tools' => [['type' => 'code_execution_20250825', 'name' => 'code_execution']],
    'messages' => [
        ['role' => 'user', 'content' => 'Run this Python code: print(sum(range(1, 101)))'],
    ],
]);

$response->content[0]->type; // 'server_tool_use'
$response->content[0]->name; // 'bash_code_execution'

$response->content[1]->type; // 'bash_code_execution_tool_result'
$response->content[1]->tool_use_id; // 'srvtoolu_01EWAZ5utP321iRHFdsvbWEV'
$response->content[1]->content['type']; // 'bash_code_execution_result'
$response->content[1]->content['stdout']; // '5050'
$response->content[1]->content['return_code']; // 0

// Container persists across turns for multi-step code execution
$response->container['id']; // 'container_011CZcynv5pD9zSXC9hAyeS2'
$response->container['expires_at']; // '2026-04-01T12:28:18.898511Z'
```

The same `tool_use_id` + `content` pattern applies to `web_fetch_tool_result`, `code_execution_tool_result`, and `tool_search_tool_result` blocks.

Creates a completion with document citations. Enable citations on document blocks, and the response will contain multiple text blocks where each cited claim includes a `citations` array pointing to exact locations in your source documents.

```
$response = $client->messages()->create([
    'model' => 'claude-opus-4-6',
    'max_tokens' => 1024,
    'messages' => [
        [
            'role' => 'user',
            'content' => [
                [
                    'type' => 'document',
                    'source' => [
                        'type' => 'text',
                        'media_type' => 'text/plain',
                        'data' => 'The grass is green. The sky is blue.',
                    ],
                    'title' => 'My Document',
                    'citations' => ['enabled' => true],
                ],
                [
                    'type' => 'text',
                    'text' => 'What color is the grass and sky?',
                ],
            ],
        ],
    ],
]);

// Uncited text
$response->content[0]->type; // 'text'
$response->content[0]->text; // 'According to the document, '
$response->content[0]->citations; // null

// Cited claim with char_location (plain text documents)
$response->content[1]->type; // 'text'
$response->content[1]->text; // 'the grass is green'
$response->content[1]->citations[0]['type']; // 'char_location'
$response->content[1]->citations[0]['cited_text']; // 'The grass is green.'
$response->content[1]->citations[0]['document_index']; // 0
$response->content[1]->citations[0]['document_title']; // 'My Document'
$response->content[1]->citations[0]['start_char_index']; // 0
$response->content[1]->citations[0]['end_char_index']; // 20
```

Five citation location types exist depending on the document source: `char_location` (plain text), `page_location` (PDFs), `content_block_location` (custom content), `web_search_result_location` (web search), and `search_result_location` (search results).

When streaming, citations arrive as `citations_delta` events on the delta object:

```
foreach ($stream as $response) {
    if ($response->delta->type === 'citations_delta') {
        $response->delta->citation['type']; // 'char_location'
        $response->delta->citation['cited_text']; // 'The grass is green.'
    }
}
```

#### `countTokens`

[](#counttokens)

Counts the number of tokens in a message without creating it.

```
$response = $client->messages()->countTokens([
    'model' => 'claude-sonnet-4-6',
    'messages' => [
        ['role' => 'user', 'content' => 'Hello, world'],
    ],
]);

$response->inputTokens; // 2095
```

#### `create streamed`

[](#create-streamed)

Creates a streamed completion for structured list of input messages.

```
$stream = $client->messages()->createStreamed([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello!'],
    ],
]);

foreach($stream as $response){
    $response->toArray();
}
// 1. iteration
[
    'type' => 'message_start',
    'message' => [
        'id' => 'msg_01SX1jLtTXgtJwB2EpSRNutG',
        'type' => 'message',
        'role' => 'assistant',
        'content' => [],
        'model' => 'claude-sonnet-4-6',
        'stop_reason' => null,
        'stop_sequence' => null,
    ],
    'usage' => [
        'input_tokens' => 9,
        'output_tokens' => 1,
        'cache_creation_input_tokens' => null,
        'cache_read_input_tokens' => null,
    ]
]
// 2. iteration
[
    'type' => 'content_block_start',
    'index' => 0,
    'content_block_start' => [
        'type' => 'text',
        'text' => '',
    ]
]
// 3. iteration
[
    'type' => 'content_block_delta',
    'index' => 0,
    'delta' => [
        'type' => 'text_delta',
        'text' => 'Hello',
    ]
]
// 4. iteration
[
    'type' => 'content_block_delta',
    'index' => 0,
    'delta' => [
        'type' => 'text_delta',
        'text' => '!',
    ]
]

// ...

// last iteration
[
    'type' => 'message_delta',
    'delta' => [
        'stop_reason' => 'end_turn',
        'stop_sequence' => null,
    ],
    'usage' => [
        'output_tokens' => 12,
        'cache_creation_input_tokens' => null,
        'cache_read_input_tokens' => null,
    ]
]
```

Creates a streamed completion for structured list of input messages with a tool call.

```
$stream = $client->messages()->createStreamed([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'What is the weather like in San Francisco?'],
    ],
    'tools' => [
        [
            'name' => 'get_weather',
            'description' => 'Get the current weather in a given location',
            'input_schema' => [
                'type' => 'object',
                'properties' => [
                    'location' => [
                        'type' => 'string',
                        'description' => 'The city and state, e.g. San Francisco, CA'
                    ],
                    'unit' => [
                        'type' => 'string',
                        'enum' => ['celsius', 'fahrenheit'],
                        'description' => 'The unit of temperature, either \"celsius\" or \"fahrenheit\"'
                    ]
                ],
                'required' => ['location']
            ]
        ]
    ]
]);

foreach($stream as $response){
    $response->toArray();
}
// 1. iteration
[
    'type' => 'message_start',
    'message' => [
        'id' => 'msg_01SX1jLtTXgtJwB2EpSRNutG',
        'type' => 'message',
        'role' => 'assistant',
        'content' => [],
        'model' => 'claude-sonnet-4-6',
        'stop_reason' => null,
        'stop_sequence' => null,
    ],
    'usage' => [
        'input_tokens' => 9,
        'output_tokens' => 1,
        'cache_creation_input_tokens' => null,
        'cache_read_input_tokens' => null,
    ]
]
// 2. iteration
[
    'type' => 'content_block_start',
    'index' => 0,
    'content_block_start' => [
        'type' => 'text',
        'text' => '',
    ]
]
// 3. iteration
[
    'type' => 'content_block_delta',
    'index' => 0,
    'delta' => [
        'type' => 'text_delta',
        'text' => 'I',
    ]
]
// 4. iteration
[
    'type' => 'content_block_delta',
    'index' => 0,
    'delta' => [
        'type' => 'text_delta',
        'text' => '\'ll help you check the current weather',
    ]
]

// ...

// 1. iteration of tool call
[
    'type' => 'content_block_start',
    'index' => 1,
    'content_block_start' => [
        'id' => 'toolu_01RDFRXpbNUGrZ1xQy443s5Q',
        'type' => 'tool_use',
        'name' => 'get_weather',
        'input' => [],
    ]
]
// 2. iteration of tool call
[
    'type' => 'content_block_delta',
    'index' => 1,
    'delta' => [
        'type' => 'input_json_delta',
        'partial_json' => '{"location',
    ]
]

// ...

// last iteration
[
    'type' => 'message_delta',
    'delta' => [
        'stop_reason' => 'end_turn',
        'stop_sequence' => null,
    ],
    'usage' => [
        'output_tokens' => 12,
        'cache_creation_input_tokens' => null,
        'cache_read_input_tokens' => null,
    ]
]
```

Creates a streamed completion with adaptive thinking. Streaming works the same way for both adaptive and `budget_tokens` thinking.

```
$stream = $client->messages()->createStreamed([
    'model' => 'claude-opus-4-6',
    'max_tokens' => 16000,
    'thinking' => [
        'type' => 'adaptive',
    ],
    'messages' => [
        ['role' => 'user', 'content' => 'What is the greatest common divisor of 1071 and 462?'],
    ],
]);

foreach ($stream as $response) {
    $response->type; // 'content_block_start', 'content_block_delta', 'content_block_stop', ...

    // Thinking block start
    $response->content_block_start->type; // 'thinking'

    // Thinking delta
    $response->delta->type; // 'thinking_delta'
    $response->delta->thinking; // 'I need to find the GCD of 1071 and 462 using the Euclidean algorithm...'

    // Signature delta (sent before content_block_stop)
    $response->delta->type; // 'signature_delta'
    $response->delta->signature; // 'EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pkiMOYds...'

    // Text delta (after thinking is complete)
    $response->delta->type; // 'text_delta'
    $response->delta->text; // 'The greatest common divisor of 1071 and 462 is **21**.'
}
```

When using `'display' => 'omitted'` with streaming, no `thinking_delta` events are emitted. You'll only receive the `signature_delta` followed by text deltas, which gives a faster time-to-first-text-token.

### `Models` Resource

[](#models-resource)

#### `list`

[](#list)

Lists the currently available models.

```
$response = $client->models()->list();

foreach ($response->data as $model) {
    $model->id; // 'claude-sonnet-4-6'
    $model->type; // 'model'
    $model->createdAt; // '2025-05-14T00:00:00Z'
    $model->displayName; // 'Claude Sonnet 4.6'
}

$response->firstId; // 'claude-sonnet-4-6'
$response->lastId; // 'claude-haiku-4-5'
$response->hasMore; // true
```

You can paginate through models using cursor-based pagination:

```
$response = $client->models()->list([
    'limit' => 10,
    'after_id' => 'claude-haiku-4-5',
]);
```

#### `retrieve`

[](#retrieve)

Gets information about a specific model.

```
$response = $client->models()->retrieve('claude-sonnet-4-6');

$response->id; // 'claude-sonnet-4-6'
$response->type; // 'model'
$response->createdAt; // '2025-05-14T00:00:00Z'
$response->displayName; // 'Claude Sonnet 4.6'
```

### `Message Batches` Resource

[](#message-batches-resource)

#### `create`

[](#create-1)

Creates a Message Batch. Processing may take up to 24 hours.

```
$response = $client->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->type; // 'message_batch'
$response->processingStatus; // 'in_progress'
$response->requestCounts->processing; // 2
$response->requestCounts->succeeded; // 0
$response->createdAt; // '2025-04-01T12:00:00Z'
$response->expiresAt; // '2025-04-02T12:00:00Z'
$response->endedAt; // null
$response->resultsUrl; // null
```

#### `retrieve`

[](#retrieve-1)

Retrieves a Message Batch. Use this to poll for completion.

```
$response = $client->batches()->retrieve('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

$response->processingStatus; // 'ended'
$response->requestCounts->succeeded; // 95
$response->requestCounts->errored; // 3
$response->resultsUrl; // 'https://api.anthropic.com/v1/messages/batches/msgbatch_.../results'
```

#### `list`

[](#list-1)

Lists Message Batches with cursor-based pagination.

```
$response = $client->batches()->list(['limit' => 10]);

foreach ($response->data as $batch) {
    $batch->id; // 'msgbatch_04Rka1yCsMLGPnR7kfPdgR8x'
    $batch->processingStatus; // 'ended'
}

$response->hasMore; // true
$response->firstId; // 'msgbatch_04Rka1yCsMLGPnR7kfPdgR8x'
$response->lastId; // 'msgbatch_07V2nm5PqB3bP8szLgTmn1EG'
```

#### `cancel`

[](#cancel)

Cancels an in-progress Message Batch.

```
$response = $client->batches()->cancel('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

$response->processingStatus; // 'canceling'
```

#### `delete`

[](#delete)

Deletes a Message Batch. Only completed batches can be deleted.

```
$response = $client->batches()->delete('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

$response->id; // 'msgbatch_04Rka1yCsMLGPnR7kfPdgR8x'
$response->type; // 'message_batch_deleted'
```

#### `results`

[](#results)

Streams the results of a completed Message Batch as JSONL. Each result contains the `custom_id` from the original request and a `result` with the response or error.

```
$response = $client->batches()->results('msgbatch_04Rka1yCsMLGPnR7kfPdgR8x');

foreach ($response as $individual) {
    $individual->customId; // 'request-1'
    $individual->result->type; // 'succeeded', 'errored', 'canceled', or 'expired'

    if ($individual->result->type === 'succeeded') {
        $individual->result->message->id; // 'msg_014VwiXbi91y3JMjcpyGBHX2'
        $individual->result->message->content[0]->text; // 'Hello! How can I help you today?'
    }

    if ($individual->result->type === 'errored') {
        $individual->result->error->type; // 'invalid_request_error'
        $individual->result->error->message; // 'max_tokens: Field required'
    }
}

$response->meta(); // rate limit and request ID headers
```

### `Completions` Resource (Legacy)

[](#completions-resource-legacy)

#### `create`

[](#create-2)

Creates a completion for the provided prompt and parameters.

```
$response = $client->completions()->create([
    'model' => 'claude-2.1',
    'prompt' => '\n\nHuman: Hello, Claude\n\nAssistant:',
    'max_tokens_to_sample' => 100,
    'temperature' => 0
]);

$response->type; // 'completion'
$response->id; // 'compl_01EKm5HZ9y6khqaSZjsX44fS'
$response->completion; // ' Hello! Nice to meet you.'
$response->stop_reason; // 'stop_sequence'
$response->model; // 'claude-2.1'
$response->stop; // '\n\nHuman:'
$response->log_id; // 'compl_01EKm5HZ9y6khqaSZjsX44fS'

$response->toArray(); // ['id' => 'compl_01EKm5HZ9y6khqaSZjsX44fS', ...]
```

#### `create streamed`

[](#create-streamed-1)

Creates a streamed completion for the provided prompt and parameters.

```
$stream = $client->completions()->createStreamed([
    'model' => 'claude-2.1',
    'prompt' => 'Hi',
    'max_tokens_to_sample' => 70,
]);

foreach($stream as $response){
    $response->completion;
}
// 1. iteration => 'I'
// 2. iteration => ' am'
// 3. iteration => ' very'
// 4. iteration => ' excited'
// ...
```

Meta Information
----------------

[](#meta-information)

On messages response object you can access the meta information returned by the API via the `meta()` method.

```
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello, world'],
    ],
]);

$meta = $response->meta();

$meta->requestId; // 'req_012nTzj6kLoP8vZ1SGANvcgR'

$meta->requestLimit->limit; // 3000
$meta->requestLimit->remaining; // 2999
$meta->requestLimit->reset; // '2024-05-01T13:29:17Z'

$meta->tokenLimit->limit; // 250000
$meta->tokenLimit->remaining; // 249984
$meta->tokenLimit->reset; // '2024-05-01T13:29:17Z'

$meta->inputTokenLimit->limit; // 20000
$meta->inputTokenLimit->remaining; // 19500
$meta->inputTokenLimit->reset; // '2024-05-01T13:29:17Z'

$meta->outputTokenLimit->limit; // 5000
$meta->outputTokenLimit->remaining; // 4900
$meta->outputTokenLimit->reset; // '2024-05-01T13:29:17Z'

$meta->custom; // additional non-standard headers
```

The `toArray()` method returns the meta information in the form originally returned by the API.

```
$meta->toArray();

// [
//   'request-id' => 'req_012nTzj6kLoP8vZ1SGANvcgR',
//   'anthropic-ratelimit-requests-limit' => 3000,
//   'anthropic-ratelimit-requests-remaining' => 2999,
//   'anthropic-ratelimit-requests-reset' => '2024-05-01T13:29:17Z',
//   'anthropic-ratelimit-tokens-limit' => 250000,
//   'anthropic-ratelimit-tokens-remaining' => 249983,
//   'anthropic-ratelimit-tokens-reset' => '2024-05-01T13:29:17Z',
//   'anthropic-ratelimit-input-tokens-limit' => 20000,
//   'anthropic-ratelimit-input-tokens-remaining' => 19500,
//   'anthropic-ratelimit-input-tokens-reset' => '2024-05-01T13:29:17Z',
//   'anthropic-ratelimit-output-tokens-limit' => 5000,
//   'anthropic-ratelimit-output-tokens-remaining' => 4900,
//   'anthropic-ratelimit-output-tokens-reset' => '2024-05-01T13:29:17Z',
// ]
```

On streaming responses you can access the meta information on the reponse stream object.

```
$stream = $client->messages()->createStreamed([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello, world'],
    ],
]);

$stream->meta();
```

For further details about the rates limits and what to do if you hit them visit the [Anthropic documentation](https://docs.anthropic.com/claude/reference/rate-limits).

Error Handling
--------------

[](#error-handling)

When the API returns an error, an `Anthropic\Exceptions\ErrorException` is thrown.

```
try {
    $result = $client->messages()->create([...]);
} catch (\Anthropic\Exceptions\ErrorException $e) {
    $e->getMessage(); // 'Overloaded'
    $e->getErrorType(); // 'overloaded_error'
    $e->getStatusCode(); // 529
}
```

For rate limit errors (HTTP 429), a dedicated `Anthropic\Exceptions\RateLimitException` is thrown. Since it extends `ErrorException`, existing `catch (ErrorException $e)` blocks will continue to work. If you want to handle rate limits specifically, catch it first:

```
try {
    $result = $client->messages()->create([...]);
} catch (\Anthropic\Exceptions\RateLimitException $e) {
    $retryAfter = $e->response->getHeaderLine('Retry-After');
} catch (\Anthropic\Exceptions\ErrorException $e) {
    // other API errors
}
```

Troubleshooting
---------------

[](#troubleshooting)

### Timeout

[](#timeout)

You may run into a timeout when sending requests to the API. The default timeout depends on the HTTP client used.

You can increase the timeout by configuring the HTTP client and passing in to the factory.

This example illustrates how to increase the timeout using Guzzle.

```
Anthropic::factory()
    ->withApiKey($apiKey)
    ->withHttpClient(new \GuzzleHttp\Client(['timeout' => $timeout]))
    ->make();
```

Testing
-------

[](#testing)

The package provides a fake implementation of the `Anthropic\Client` class that allows you to fake the API responses.

To test your code ensure you swap the `Anthropic\Client` class with the `Anthropic\Testing\ClientFake` class in your test case.

The fake responses are returned in the order they are provided while creating the fake client.

All responses are having a `fake()` method that allows you to easily create a response object by only providing the parameters relevant for your test case.

```
use Anthropic\Testing\ClientFake;
use Anthropic\Responses\Completions\CreateResponse;

$client = new ClientFake([
    CreateResponse::fake([
        'completion' => 'awesome!',
    ]),
]);

$completion = $client->completions()->create([
    'model' => 'claude-2.1',
    'prompt' => '\n\nHuman: PHP is \n\nAssistant:',
    'max_tokens_to_sample' => 100,
]);

expect($completion['completion'])->toBe('awesome!');
```

In case of a streamed response you can optionally provide a resource holding the fake response data.

```
use Anthropic\Testing\ClientFake;
use Anthropic\Responses\Messages\CreateStreamedResponse;

$client = new ClientFake([
    CreateStreamedResponse::fake(fopen('file.txt', 'r'););
]);

$completion = $client->messages()->createStreamed([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'Hello!'],
    ],
]);

expect($response->getIterator()->current())
        ->type->toBe('message_start');
```

After the requests have been sent there are various methods to ensure that the expected requests were sent:

```
// assert completion create request was sent
$client->assertSent(Completions::class, function (string $method, array $parameters): bool {
    return $method === 'create' &&
        $parameters['model'] === 'claude-2.1' &&
        $parameters['prompt'] === 'PHP is ';
});
// or
$client->completions()->assertSent(function (string $method, array $parameters): bool {
    // ...
});

// assert 2 completion create requests were sent
$client->assertSent(Completions::class, 2);

// assert no completion create requests were sent
$client->assertNotSent(Completions::class);
// or
$client->completions()->assertNotSent();

// assert no requests were sent
$client->assertNothingSent();
```

To write tests expecting the API request to fail you can provide a `Throwable` object as the response.

```
$client = new ClientFake([
    new \Anthropic\Exceptions\ErrorException([
        'message' => 'Overloaded',
        'type' => 'overloaded_error',
    ], 529)
]);

// the `ErrorException` will be thrown
$completion = $client->completions()->create([
    'model' => 'claude-2.1',
    'prompt' => '\n\nHuman: PHP is \n\nAssistant:',
    'max_tokens_to_sample' => 100,
]);
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Mozex](https://github.com/mozex)
- [Nuno Maduro](https://github.com/nunomaduro) and [Sandro Gehri](https://github.com/gehrisandro) for their work on [openai-php](https://github.com/openai-php/client), which inspired this package
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

59

—

FairBetter than 99% of packages

Maintenance88

Actively maintained with recent releases

Popularity50

Moderate usage in the ecosystem

Community22

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 97.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~56 days

Recently: every ~0 days

Total

13

Last Release

74d ago

PHP version history (2 changes)1.0.0PHP ^8.1.0

1.2.0PHP ^8.2.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4d33a9cb8263eab6fa251e57fc763c5c6977701e5cafa0edc538c4651bb9780?d=identicon)[mozex](/maintainers/mozex)

---

Top Contributors

[![mozex](https://avatars.githubusercontent.com/u/18025667?v=4)](https://github.com/mozex "mozex (156 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")

---

Tags

aianthropicapi-clientchatbotclaudegenerative-aillmphpsdkstreamingtool-usephpapiclientsdklanguageprocessingnaturalclaudeanthropicClaude OpusClaude SonnetClaude Haiku

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/mozex-anthropic-php/health.svg)

```
[![Health](https://phpackages.com/badges/mozex-anthropic-php/health.svg)](https://phpackages.com/packages/mozex-anthropic-php)
```

###  Alternatives

[openai-php/client

OpenAI PHP is a supercharged PHP API client that allows you to interact with the Open AI API

5.8k22.6M232](/packages/openai-php-client)[mozex/anthropic-laravel

Anthropic PHP for Laravel is a supercharged PHP API client that allows you to interact with the Anthropic API

71226.4k1](/packages/mozex-anthropic-laravel)[theodo-group/llphant

LLPhant is a library to help you build Generative AI applications.

1.5k311.5k5](/packages/theodo-group-llphant)[getbrevo/brevo-php

Official Brevo provided RESTFul API V3 php library

963.1M35](/packages/getbrevo-brevo-php)[google-gemini-php/client

Gemini API is a supercharged PHP API client that allows you to interact with the Gemini API

402986.7k21](/packages/google-gemini-php-client)[openai-php/symfony

Symfony Bundle for OpenAI

215715.5k3](/packages/openai-php-symfony)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
