---
title: Index a knowledge base document
url: https://developers.wpengine.com/docs/ai/api/reference/operations/indexdocument/
image: https://developers.wpengine.com/og/docs/ai/api/reference/operations/indexdocument.png
---

# Index a knowledge base document

POST

/v1/kb/collections/{id}/documents

Select code sample

```php
<?php


$client = new \GuzzleHttp\Client();


$response = $client->request('POST', 'https://api.ai.wpengine.com/v1/kb/collections/example/documents', [
  'body' => '{ "id": "example", "content": "example", "title": "example", "type": "example", "uri": "example", "language": "example", "created_at": "2026-04-15T12:00:00Z", "modified_at": "2026-04-15T12:00:00Z", "metadata": { "status": "publish", "category": "news", "tags": [ "guide", "billing" ] }, "elements": [ { "tag": "a", "count": 2, "href": "https://example.org/page", "domain": "example.org", "scheme": "https", "has_query": true, "internal": false, "target": "_blank", "rel": [ "nofollow", "noopener" ] } ], "elements_truncated": true }',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);


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

- Current environment

Indexes a single document into the collection. “content” is required and is the text indexed for search. An “id” may be supplied to make index idempotent (re-indexing the same id replaces the document); when omitted the gateway generates one. The “id” must not contain “/”. Concurrent writes to the same id are resolved last-writer-wins. Requires a valid WP Engine bearer token.

## Authorizations

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

## Parameters

### Path Parameters

**id**

required

string

The collection ID.

## Request Bodyrequired

Media typeapplication/json

object

**id**

Stable document id. Supply it to make index idempotent (re-indexing the same id replaces the document); generated when omitted.

string

**content**

required

The document text indexed for search.

string

**title**

string

**type**

Document type (e.g. the WordPress post type).

string

**uri**

Canonical URL for the document.

string

**language**

ISO 639-1 language code.

string

**created_at**

string format: date-time

**modified_at**

string format: date-time

**metadata**

Free-form metadata; values are stored as keywords for exact-match filtering.

object

**_key_**

additional properties

any

### Example

```json
{
  "status": "publish",
  "category": "news",
  "tags": [
    "guide",
    "billing"
  ]
}
```

**elements**

The document’s HTML elements (links, images, embeds), one entry per distinct element with its occurrence count, at most 256 KiB encoded. Send the whole list with every write, or an empty list when the document has none: a write without the field stores the document without elements, removing any stored before. Elements are used by document listing and element aggregations and are not returned when a document is fetched.

Array\<object>

<= 1000 items

One distinct HTML element of a document. `href` or `src` is the element’s main URL, without its fragment or query string (the WordPress content parameters `p`, `page_id`, `attachment_id`, `cat`, `tag` and `author` are kept, sorted by name); `domain`, `scheme`, `has_query` and `internal` describe it. A link with a non-http scheme carries only `scheme`.

object

**tag**

required

Lowercase tag name, such as `a`, `img`, `iframe` or `embed`.

string

/^\[a-z]\[a-z0-9-]{0,31}$/

**count**

required

How many times the element occurs in the document.

integer

\>= 1 <= 1000000

**href**

Link URL.

string

<= 2048 characters

**src**

Source URL.

string

<= 2048 characters

**domain**

Lowercase host of the URL.

string

<= 253 characters

**scheme**

Lowercase URL scheme, such as `https` or `mailto`.

string

/^\[a-z]\[a-z0-9+.-]{0,31}$/

**has_query**

Whether the URL had a query string.

boolean

**internal**

Whether the URL points at the site itself.

boolean

**target**

Link target, such as `_blank`.

string

<= 64 characters

**rel**

Link rel tokens, lowercase.

Array\<string>

<= 16 items

**alt**

Image alt text. An empty string means the attribute is present without text; omitted means the attribute is missing.

string

<= 1024 characters

**ext**

Custom element attributes, grouped by type. Names are lowercase letters, digits, `-` and `_`, starting with a letter, at most 64 characters; an element has at most 16 and a request at most 64 distinct names.

object

**keyword**

Exact-match text values, each a string or a list of up to 16 strings of at most 1024 bytes. Values of an attribute the site declares as an enum are matched in lowercase, so send them lowercase.

object

**_key_**

additional properties

One of:

- [string](https://developers.wpengine.com/docs/ai/api/reference/operations/indexdocument/#tab-panel-0-0)
- [Array\<string>](https://developers.wpengine.com/docs/ai/api/reference/operations/indexdocument/#tab-panel-0-1)

string

<= 1024 characters

**url**

URL values, at most 2048 bytes. An absolute http or https URL is stored as filters compare it: scheme and host lowercased, fragment and query string dropped except WordPress content parameters.

object

**_key_**

additional properties

string

<= 2048 characters

**boolean**

object

**_key_**

additional properties

boolean

**long**

Whole numbers between -2^53 and 2^53.

object

**_key_**

additional properties

integer format: int64

### Example

```json
{
  "tag": "a",
  "count": 2,
  "href": "https://example.org/page",
  "domain": "example.org",
  "scheme": "https",
  "has_query": true,
  "internal": false,
  "target": "_blank",
  "rel": [
    "nofollow",
    "noopener"
  ]
}
```

**elements_truncated**

True when the client dropped elements to stay within its limits, so the list is incomplete.

boolean

## Responses

### 200

An existing id was re-indexed — “updated” if the document changed, or “unchanged” if it was identical (a no-op).

Media typeapplication/json

object

**id**

required

The document id (supplied or generated).

string

**result**

required

string

Allowed values: created updated unchanged

#### Example

```json
{
  "result": "created"
}
```

### 201

The document was created

Media typeapplication/json

object

**id**

required

The document id (supplied or generated).

string

**result**

required

string

Allowed values: created updated unchanged

#### Example

```json
{
  "result": "created"
}
```

### 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"
```

### 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

### 503

The knowledge base is not currently available. Retry after a short delay.

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"}}]}
```
