---
title: Create a chat completion
url: https://developers.wpengine.com/docs/ai/api/reference/operations/createchatcompletion/
image: https://developers.wpengine.com/og/docs/ai/api/reference/operations/createchatcompletion.png
---

# Create a chat completion

POST

/v1/chat/completions

Select code sample

```php
<?php


$client = new \GuzzleHttp\Client();


$response = $client->request('POST', 'https://api.ai.wpengine.com/v1/chat/completions', [
  'body' => '{ "model": "google/gemini-3.5-flash", "messages": [ { "role": "user", "content": "Say hello in one short sentence." } ] }',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);


echo $response->getBody();
```

- Current environment

Requires a valid WP Engine bearer token. API keys must carry the “chat:write” permission.

## Authorizations

- **[bearerAuth](https://developers.wpengine.com/docs/ai/api/reference/#bearerauth)**

## Request Bodyrequired

Media typeapplication/json

object

**model**

required

Model identifier in the format “provider/model-name” (e.g. “openai/gpt-oss-120b-maas”, “google/gemini-3.5-flash”, “anthropic/claude-sonnet-4-6”).

string

### Example

```
google/gemini-3.5-flash
```

**messages**

required

Array\<object>

\>= 1 items

object

**role**

required

string

Allowed values: system user assistant tool

### Example

```
user
```

**content**

required

string

### Example

```
Say hello in one short sentence.
```

**tool_calls**

Tool calls made by the assistant.

Array\<object>

object

**id**

required

string

**type**

required

string

### Example

```
function
```

**function**

required

object

**name**

required

string

**description**

string

**arguments**

JSON-encoded arguments for the function call.

string

**parameters**

JSON Schema describing the function parameters.

**tool_call_id**

ID of the tool call this message is a response to (role must be “tool”).

string

**annotations**

Sources the answer drew on when web search ran. Returned on assistant messages only; don’t send it back in requests.

Array\<object>

object

**type**

required

string

Allowed values: url_citation

**url_citation**

required

object

**url**

required

Link to the source. It may be a redirect link that expires.

string

**title**

string

**start_index**

Start of the cited span in the message content.

integer

**end_index**

End of the cited span in the message content.

integer

**temperature**

Sampling temperature. See the model’s `parameters.temperature` metadata on /models for the accepted range and support. Rejected with HTTP 400 when out of range, unsupported, or not applicable.

number format: double

**top\_p**

Nucleus sampling parameter.

number format: double

**max_tokens**

Hard upper bound on output tokens for this request, forwarded to the model provider. Generation stops when the limit is reached; the response may be truncated mid-content rather than rejected. `finish_reason: "length"` (OpenAI-compatible routes) indicates the budget was hit. On reasoning-capable models (see capabilities on GET /v1/models), internal reasoning tokens may count against this budget alongside visible output. Per-model valid ranges are published in GET /v1/models/{model_id}/schema.

integer

**stream**

If true, the response is streamed as Server-Sent Events.

boolean

**stop**

Stop sequences.

Array\<string>

**tools**

Tools available to the model. Function tools invoke caller-defined functions; native `web_search` tools enable server-side search on models that advertise the `web_search` capability (see GET /v1/models).

Array

One of: discriminator: type

- [object](https://developers.wpengine.com/docs/ai/api/reference/operations/createchatcompletion/#tab-panel-0-0)
- [object](https://developers.wpengine.com/docs/ai/api/reference/operations/createchatcompletion/#tab-panel-0-1)

object

**type**

required

string

Allowed values: function

### Example

```
function
```

**function**

required

object

**name**

required

string

**description**

string

**arguments**

JSON-encoded arguments for the function call.

string

**parameters**

JSON Schema describing the function parameters.

**tool_choice**

Controls how the model selects tools. Can be “auto”, “none”, “required”, or an object specifying a particular function.

**response_format**

Structured output format. See the model’s `parameters.response_format_type` metadata on /models for the accepted values. Rejected with HTTP 400 when the type is unsupported or not applicable.

object

**type**

required

The response format type. Use “text” for plain text (default), “json_object” for unstructured JSON mode, or “json_schema” for structured output that conforms to a provided JSON Schema.

string

Allowed values: text json_object json_schema

### Example

```
json_schema
```

**json_schema**

Describes the JSON Schema the model must follow when response_format.type is “json_schema”.

object

**name**

required

A name identifying this schema (for caching and logging).

string

### Example

```
recipe
```

**description**

Optional human-readable description of the schema purpose.

string

**schema**

required

A JSON Schema object describing the desired output structure. Supports standard JSON Schema types (object, array, string, number, integer, boolean) with provider-specific subset limitations.

object

**_key_**

additional properties

any

**strict**

Whether to request strict schema adherence. When true, the gateway forwards this preference to providers that support strict/JSON-schema-constrained decoding (for example, OpenAI and Anthropic). Not all providers honor this flag, and the gateway does not independently validate or guarantee schema compliance.

boolean

**reasoning_effort**

Catalog-native reasoning effort. Allowed values are the model’s `parameters.reasoning_effort` on GET /v1/models. Omit to use the provider default. Models that do not publish an enum reject any non-empty value. Mutually exclusive with `provider_options.thinking_config` on `google/*` models.

string

### Example

```
high
```

**provider_options**

Provider-specific parameters. Supported `openai/*` and `google/*` models.

object

**_key_**

additional properties

any

### Example

```json
{
  "thinking_config": {
    "thinking_budget": 1024,
    "include_thoughts": true
  }
}
```

### Example

```json
{
  "model": "google/gemini-3.5-flash",
  "messages": [
    {
      "role": "user",
      "content": "Say hello in one short sentence."
    }
  ]
}
```

## Responses

### 200

Chat completion response. When stream is false, returns a single JSON object. When stream is true, returns Server-Sent Events with chunked JSON payloads terminated by a “data: \[DONE]” message.

Select media type

object

**id**

required

string

**object**

required

string

**created**

required

Unix timestamp.

integer format: int64

**model**

required

string

**choices**

required

Array\<object>

object

**index**

required

integer

**message**

object

**role**

required

string

Allowed values: system user assistant tool

**content**

required

string

**tool_calls**

Tool calls made by the assistant.

Array\<object>

object

**id**

required

string

**type**

required

string

**function**

required

object

**name**

required

string

**description**

string

**arguments**

JSON-encoded arguments for the function call.

string

**parameters**

JSON Schema describing the function parameters.

**tool_call_id**

ID of the tool call this message is a response to (role must be “tool”).

string

**annotations**

Sources the answer drew on when web search ran. Returned on assistant messages only; don’t send it back in requests.

Array\<object>

object

**type**

required

string

Allowed values: url_citation

**url_citation**

required

object

**url**

required

Link to the source. It may be a redirect link that expires.

string

**title**

string

**start_index**

Start of the cited span in the message content.

integer

**end_index**

End of the cited span in the message content.

integer

**finish_reason**

string

Allowed values: stop length tool_calls content_filter model_context_window_exceeded

**usage**

object

**prompt_tokens**

required

Total prompt tokens, including any cached or cache-write tokens.

integer

**completion_tokens**

required

Total completion tokens, including any reasoning tokens.

integer

**total_tokens**

required

integer

**prompt_tokens_details**

object

**cached_tokens**

Prompt tokens served from cache, already counted in prompt_tokens. Omitted when zero.

integer

**cache_write_tokens**

Prompt tokens written to cache, already counted in prompt_tokens. Omitted when zero.

integer

**completion_tokens_details**

object

**reasoning_tokens**

Tokens the model spent reasoning before answering, already counted in completion_tokens. Omitted when zero.

integer

#### Example

```json
{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "choices": [
    {
      "message": {
        "role": "system",
        "content": "Say hello in one short sentence.",
        "tool_calls": [
          {
            "type": "function"
          }
        ],
        "annotations": [
          {
            "type": "url_citation"
          }
        ]
      },
      "finish_reason": "stop"
    }
  ]
}
```

### 400

Invalid request body or parameters. On agent create and update, error type “profile_unavailable” means the requested profile is not available to the caller.

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 401

Missing or invalid bearer token

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

#### Headers

**WWW-Authenticate**

string

##### Example

```
Bearer realm="ai-services"
```

### 402

The account’s credit balance is exhausted. Grant or top up credits before retrying. Distinct from 429, which is edge rate limiting.

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 403

The token is valid, but the request is forbidden. Error type “permission_error” means the token’s scope/permission is insufficient or the authenticated user is not authorized for the target account; “entitlement_required” means the account may not use WP Engine AI, with error_code giving why when known (not_eligible, terms_required, not_enabled or suspended) and portal_url where to fix it; “account_required” means no billing account could be resolved; and “billing_account_pending” means billing isn’t set up for the account yet, usually because its setup after AI was turned on hasn’t finished. Retry shortly. On /v1/chat/completions when content moderation is enabled, and on /v1/sessions/{session_id}/events, error type “content_policy_violation” instead means the request content was blocked by content moderation policy; that response never identifies which filter or category matched.

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 404

The requested resource was not found

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 413

Request body exceeds the 64 KiB limit

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 429

Rate limit exceeded. The request was throttled at the edge; wait and retry later. The response body is a short HTML page generated by the load balancer, not a structured JSON error — clients should rely on the 429 status code rather than parsing the body.

Media typetext/html

string

### 502

Upstream provider returned an error

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### 503

A required dependency is temporarily unavailable. Retry after a short delay with exponential back-off. An entitlement lookup failure uses error type “entitlement_unavailable”. A model without complete rate coverage uses error type “model_unpriced”. A credit balance that can’t be read uses error type “balance_unavailable”.

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

### default

Upstream provider error passed through with its original status code and response body. The shape may vary by provider.

Media typeapplication/json

object

**error**

required

object

**message**

required

string

**type**

required

string

**error_code**

Stable, machine-readable cause, set by routes that document their codes (the AI readiness and account AI routes, and an entitlement_required refusal, where it is one of not_eligible, terms_required, not_enabled or suspended); absent elsewhere and on errors from shared layers such as authentication. Clients must allow new codes.

string

**portal_url**

Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.

string

**code**

required

integer

**request_id**

required

Correlation ID for this request, matching the X-Request-ID response header — a 32-character trace ID behind the load balancer, otherwise a UUID. Quote it in support reports.

string

#### Example

```json
{
  "error": {
    "type": "invalid_request_error",
    "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5"
  }
}
```

## Was this helpful?

Thanks for the feedback!

```json
{"@context":"https://schema.org","@graph":[{"@type":"WebSite","@id":"https://developers.wpengine.com/#website","name":"WP Engine Product Documentation","url":"https://developers.wpengine.com/","description":"Resources for developing, deploying, and scaling on WP Engine.","inLanguage":"en-US","keywords":["API documentation","product documentation","headless WordPress","managed WordPress hosting"],"publisher":{"@id":"https://wpengine.com/#organization"}}]}
```
