Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build LLM-powered apps with the Anthropic Claude API or SDK across Python, TypeScript, Java, Go, Ruby, C#, and PHP.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
php/claude-api/README.md
1# Claude API — PHP23> **Note:** The PHP SDK is the official Anthropic SDK for PHP. A beta tool runner is available via `$client->beta->messages->toolRunner()`. Structured output helpers are supported via `StructuredOutputModel` classes. Agent SDK is not available. Bedrock, Vertex AI, and Foundry clients are supported.45## Installation67```bash8composer require "anthropic-ai/sdk"9```1011## Client Initialization1213```php14use Anthropic\Client;1516// Using API key from environment variable17$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));18```1920### Amazon Bedrock2122```php23use Anthropic\Bedrock\MantleClient;2425// Messages-API Bedrock endpoint. Reads AWS credentials from env.26$client = new MantleClient(awsRegion: 'us-east-1');27```2829Model IDs on Bedrock take an `anthropic.` prefix — e.g. `model: 'anthropic.claude-opus-4-8'`.3031### Google Vertex AI3233```php34use Anthropic\Vertex;3536// Constructor is private. Parameter is `location`, not `region`.37$client = Vertex\Client::fromEnvironment(38location: 'us-east5',39projectId: 'my-project-id',40);41```4243### Anthropic Foundry4445```php46use Anthropic\Foundry;4748// Constructor is private. baseUrl or resource is required.49$client = Foundry\Client::withCredentials(50apiKey: getenv('ANTHROPIC_FOUNDRY_API_KEY'),51baseUrl: 'https://<resource>.services.ai.azure.com/anthropic/v1',52);53```5455---5657## Basic Message Request5859```php60$message = $client->messages->create(61model: 'claude-opus-4-8',62maxTokens: 16000,63messages: [64['role' => 'user', 'content' => 'What is the capital of France?'],65],66);6768// content is an array of polymorphic blocks (TextBlock, ToolUseBlock,69// ThinkingBlock). Accessing ->text on content[0] without checking the block70// type will throw if the first block is not a TextBlock (e.g., when extended71// thinking is enabled and a ThinkingBlock comes first). Always guard:72foreach ($message->content as $block) {73if ($block->type === 'text') {74echo $block->text;75}76}77```7879If you only want the first text block:8081```php82foreach ($message->content as $block) {83if ($block->type === 'text') {84echo $block->text;85break;86}87}88```8990---9192## Extended Thinking9394**Adaptive thinking is the recommended mode for Claude 4.6+ models.** Claude decides dynamically when and how much to think.9596```php97use Anthropic\Messages\ThinkingBlock;9899$message = $client->messages->create(100model: 'claude-opus-4-8',101maxTokens: 16000,102thinking: ['type' => 'adaptive', 'display' => 'summarized'], // display opt-in: default is omitted (empty thinking text) on Fable 5 / Mythos 5 / Opus 4.8 / 4.7103messages: [104['role' => 'user', 'content' => 'Solve: 27 * 453'],105],106);107108// ThinkingBlock(s) precede TextBlock in content109foreach ($message->content as $block) {110if ($block instanceof ThinkingBlock) {111echo "Thinking:\n{$block->thinking}\n\n";112// $block->signature is an opaque string — preserve verbatim if113// passing thinking blocks back in multi-turn conversations114} elseif ($block->type === 'text') {115echo "Answer: {$block->text}\n";116}117}118```119120> **Fable 5, Opus 4.8, Opus 4.7, Opus 4.6, and Sonnet 4.6:** Use adaptive thinking (above). `['type' => 'enabled', 'budgetTokens' => N]` is removed on Fable 5, Opus 4.8, and 4.7 (400 if sent); deprecated on Opus 4.6 and Sonnet 4.6.121> **Older models:** Use `thinking: ['type' => 'enabled', 'budgetTokens' => N]` (budget must be < `maxTokens`, min 1024).122123`$block->type === 'thinking'` also works for the check; `instanceof` narrows for PHPStan.124125---126127## Prompt Caching128129`system:` takes an array of text blocks; set `cacheControl` on the last block. Array-shape syntax (camelCase keys) is idiomatic. For placement patterns and the silent-invalidator audit checklist, see `shared/prompt-caching.md`.130131```php132$message = $client->messages->create(133model: 'claude-opus-4-8',134maxTokens: 16000,135system: [136['type' => 'text', 'text' => $longSystemPrompt, 'cacheControl' => ['type' => 'ephemeral']],137],138messages: [['role' => 'user', 'content' => 'Summarize the key points']],139);140```141142For 1-hour TTL: `'cacheControl' => ['type' => 'ephemeral', 'ttl' => '1h']`. There's also a top-level `cacheControl:` on `messages->create(...)` that auto-places on the last cacheable block.143144Verify hits via `$message->usage->cacheCreationInputTokens` / `$message->usage->cacheReadInputTokens`.145146---147148## Stop Details149150When `stopReason` is `'refusal'`, the response includes structured `stopDetails`:151152```php153if ($message->stopReason === 'refusal' && $message->stopDetails !== null) {154echo "Category: " . $message->stopDetails->category . "\n"; // e.g. "cyber", "bio", "reasoning_extraction", "frontier_llm", or null — see docs for the full set155echo "Explanation: " . $message->stopDetails->explanation . "\n";156}157```158159**Refusal fallbacks (Claude Fable 5) — opt in by default.** Fallbacks are opt-in: without them a refused request simply stops. New `claude-fable-5` code should include the server-side `fallbacks` parameter (beta header `server-side-fallback-2026-06-01`, fallback model `claude-opus-4-8`, on the beta messages call) by default. The exact PHP binding (and the client-side middleware for providers without server-side support) is not documented here — WebFetch the PHP SDK repo's `examples/` from `shared/live-sources.md`; full semantics in `shared/model-migration.md` → Migrating to Claude Fable 5 → `refusal` stop reason.160161---162163## Error Type164165`APIStatusException` exposes a `->type` property for programmatic error classification:166167```php168try {169$client->messages->create(...);170} catch (\Anthropic\Core\Exceptions\APIStatusException $e) {171echo $e->type?->value; // "rate_limit_error", "overloaded_error", etc.172}173```174