# Messages

**Package:** Anthropic PHP | **Version:** 1 | **URL:** https://mozex.dev/docs/anthropic-php/v1/usage/messages

---

The Messages API is the primary way to interact with Claude through this SDK. You send a list of messages (a conversation), and Claude responds with a new message.

## Creating a message

Pass an array of parameters to `create()`. At minimum, you need a `model`, `max_tokens` limit, and at least one message:

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

The `messages` array represents a conversation. Each message has a `role` (`user` or `assistant`) and `content` (a string or an array of content blocks).

## Response structure

The `create()` method returns a `CreateResponse` object. Here's what you get back:

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

### Content blocks

The response content is an array of typed blocks. For a simple text response, there's one block:

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

Different features produce different content block types. [Tool Use](https://mozex.dev/docs/anthropic-php/v1/usage/tool-use) adds `tool_use` blocks. [Thinking](https://mozex.dev/docs/anthropic-php/v1/usage/thinking) adds `thinking` blocks. [Server Tools](https://mozex.dev/docs/anthropic-php/v1/usage/server-tools) add `server_tool_use` and result blocks.

### Token usage

Every response includes token counts:

```php
$response->usage->inputTokens;               // 10
$response->usage->outputTokens;              // 19
$response->usage->cacheCreationInputTokens;  // 0
$response->usage->cacheReadInputTokens;      // 0
```

If you're using [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching), the cache fields tell you how many tokens were written to or read from cache.

For cache breakdowns by window type:

```php
$response->usage->cacheCreation; // null or CreateResponseUsageCacheCreation
$response->usage->cacheCreation?->ephemeral5mInputTokens;  // 456
$response->usage->cacheCreation?->ephemeral1hInputTokens;  // 100
```

The `serviceTier` field shows which processing tier handled the request:

```php
$response->usage->serviceTier; // 'standard', 'priority', 'batch', or null
```

When using [server tools](https://mozex.dev/docs/anthropic-php/v1/usage/server-tools), you can check tool usage counts:

```php
$response->usage->serverToolUse; // null or CreateResponseUsageServerToolUse
$response->usage->serverToolUse?->webSearchRequests; // 3
```

### Converting to an array

Every response object has a `toArray()` method that returns the raw data as a PHP array:

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

This is useful for logging, serialization, or when you need to pass the response to code that expects plain arrays.

## Multi-turn conversations

To have a back-and-forth conversation, include the full message history in each request. The API is stateless, so you need to send the entire conversation every time:

```php
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        ['role' => 'user', 'content' => 'What is PHP?'],
        ['role' => 'assistant', 'content' => 'PHP is a server-side scripting language...'],
        ['role' => 'user', 'content' => 'What version should I use?'],
    ],
]);
```

Messages must alternate between `user` and `assistant` roles. The conversation always starts with a `user` message.

## System messages

Use the `system` parameter to give Claude instructions, persona, or context that applies to the whole conversation:

```php
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'system' => 'You are a helpful PHP expert. Answer concisely.',
    'messages' => [
        ['role' => 'user', 'content' => 'What is the null coalescing operator?'],
    ],
]);
```

The system message isn't part of the `messages` array. It's a separate top-level parameter.

## Vision

Claude can read images in the same request as text. Instead of a string, pass an array of content blocks in the message's `content`:

```php
$imagePath = '/path/to/photo.jpg';

$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'messages' => [
        [
            'role' => 'user',
            'content' => [
                [
                    'type' => 'text',
                    'text' => 'What is in this image?',
                ],
                [
                    'type' => 'image',
                    'source' => [
                        'type' => 'base64',
                        'media_type' => 'image/jpeg',
                        'data' => base64_encode(file_get_contents($imagePath)),
                    ],
                ],
            ],
        ],
    ],
]);
```

Supported media types are `image/jpeg`, `image/png`, `image/gif`, and `image/webp`. You can detect the MIME type from the file itself with PHP's `finfo`:

```php
$mimeType = (new finfo(FILEINFO_MIME_TYPE))->file($imagePath);
```

You can also pass images by URL instead of embedding them:

```php
[
    'type' => 'image',
    'source' => [
        'type' => 'url',
        'url' => 'https://example.com/photo.jpg',
    ],
]
```

Multiple images in a single message work too. Add as many image blocks as you need to the content array alongside the text block.

## Tracking users

Pass a `metadata` object with a `user_id` to associate each request with a user in your system. These IDs appear in the Anthropic Console for analytics and abuse detection:

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

Use an opaque identifier like a UUID or hash. Don't send personal information like names or email addresses.

## Passing parameters

This client doesn't validate or transform request parameters. Whatever you pass in the array goes directly to the Anthropic API as JSON. This means:

- New API parameters work immediately, even before the client adds explicit support
- You can pass any parameter documented in the [Anthropic API reference](https://platform.claude.com/docs/en/api/messages/create)
- If you pass an invalid parameter, the API returns an error (see [Error Handling](https://mozex.dev/docs/anthropic-php/v1/reference/error-handling))

For example, setting temperature and top_p:

```php
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'temperature' => 0.7,
    'top_p' => 0.9,
    'messages' => [
        ['role' => 'user', 'content' => 'Write a haiku about PHP.'],
    ],
]);
```

## Stop sequences

You can tell Claude to stop generating when it produces a specific string:

```php
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 1024,
    'stop_sequences' => ['```'],
    'messages' => [
        ['role' => 'user', 'content' => 'Write a PHP function, then explain it.'],
    ],
]);

$response->stop_reason;   // 'stop_sequence'
$response->stop_sequence; // '```'
```

When Claude hits a stop sequence, `stop_reason` is `'stop_sequence'` and `stop_sequence` tells you which one matched.

## Handling refusals

When safety classifiers intervene mid-generation, the API returns `stop_reason: 'refusal'` along with a `stop_details` object that explains why. The response is otherwise well-formed, so you can treat it like any other completion and just branch on `stop_reason`:

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

if ($response->stop_reason === 'refusal') {
    $response->stop_details->type;        // 'refusal'
    $response->stop_details->category;    // 'cyber', 'bio', or null
    $response->stop_details->explanation; // human-readable text, or null
}
```

`stop_details` is only populated on refusal responses; on a normal completion it's `null`. The `explanation` text isn't guaranteed to be stable between requests, so don't parse it. Treat `category` as the machine-readable signal and show `explanation` to the user if you need to display something.

## The `pause_turn` stop reason

Long-running turns that hit internal limits come back with `stop_reason: 'pause_turn'` instead of `'end_turn'`. The response is valid and complete for the work done so far. To let Claude continue, send the same response back as the next assistant message:

```php
$response = $client->messages()->create([
    'model' => 'claude-sonnet-4-6',
    'max_tokens' => 8192,
    'messages' => $messages,
]);

while ($response->stop_reason === 'pause_turn') {
    $messages[] = [
        'role' => 'assistant',
        'content' => array_map(fn ($block) => $block->toArray(), $response->content),
    ];

    $response = $client->messages()->create([
        'model' => 'claude-sonnet-4-6',
        'max_tokens' => 8192,
        'messages' => $messages,
    ]);
}
```

You don't need any special parameter to resume, just echo the paused content back in the next turn. If you don't want to resume, leave it as is and treat it like a normal reply.

## Inference region

Responses include the geographic region that processed the request:

```php
$response->usage->inferenceGeo; // 'us', 'eu', or null
```

Useful for data-residency logging or routing decisions. The field is `null` when the API doesn't report a region.

---

For the full list of parameters, content block types, and the latest API changes, see the [Messages API reference](https://platform.claude.com/docs/en/api/messages/create) on the Anthropic docs.

---

## Table of Contents

- [Introduction](https://mozex.dev/docs/anthropic-php/v1)
- [AI Integration](https://mozex.dev/docs/anthropic-php/v1/ai-integration)
- [Support Us](https://mozex.dev/docs/anthropic-php/v1/support-us)
- [Requirements](https://mozex.dev/docs/anthropic-php/v1/requirements)
- [Changelog](https://mozex.dev/docs/anthropic-php/v1/changelog)
- [Contributing](https://mozex.dev/docs/anthropic-php/v1/contributing)
- [Questions & Issues](https://mozex.dev/docs/anthropic-php/v1/questions-and-issues)
- [About Mozex](https://mozex.dev/docs/anthropic-php/v1/about)

### Usage

- [Messages](https://mozex.dev/docs/anthropic-php/v1/usage/messages)
- [Streaming](https://mozex.dev/docs/anthropic-php/v1/usage/streaming)
- [Tool Use](https://mozex.dev/docs/anthropic-php/v1/usage/tool-use)
- [Thinking](https://mozex.dev/docs/anthropic-php/v1/usage/thinking)
- [Server Tools](https://mozex.dev/docs/anthropic-php/v1/usage/server-tools)
- [Citations](https://mozex.dev/docs/anthropic-php/v1/usage/citations)
- [Token Counting](https://mozex.dev/docs/anthropic-php/v1/usage/token-counting)
- [Models](https://mozex.dev/docs/anthropic-php/v1/usage/models)
- [Batches](https://mozex.dev/docs/anthropic-php/v1/usage/batches)
- [Completions](https://mozex.dev/docs/anthropic-php/v1/usage/completions)
- [Files](https://mozex.dev/docs/anthropic-php/v1/usage/files)

### Reference

- [Configuration](https://mozex.dev/docs/anthropic-php/v1/reference/configuration)
- [Error Handling](https://mozex.dev/docs/anthropic-php/v1/reference/error-handling)
- [Meta Information](https://mozex.dev/docs/anthropic-php/v1/reference/meta-information)
- [Testing](https://mozex.dev/docs/anthropic-php/v1/reference/testing)