Bulk-index knowledge base documents
package main
import ( "fmt" "strings" "net/http" "io")
func main() {
url := "https://api.ai.wpengine.com/v1/kb/collections/example/documents/bulk"
payload := strings.NewReader("{ \"documents\": [ { \"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 } ] }")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>") req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close() body, _ := io.ReadAll(res.Body)
fmt.Println(res) fmt.Println(string(body))
}const url = 'https://api.ai.wpengine.com/v1/kb/collections/example/documents/bulk';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"documents":[{"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}]}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}<?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.ai.wpengine.com/v1/kb/collections/example/documents/bulk', [ 'body' => '{ "documents": [ { "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();curl --request POST \ --url https://api.ai.wpengine.com/v1/kb/collections/example/documents/bulk \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "documents": [ { "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 } ] }'Indexes multiple documents in one request. Each item is reported independently, so one invalid document does not fail the batch. A request may contain at most 100 documents. Requires a valid WP Engine bearer token.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The collection ID.
Request Bodyrequired
Section titled “Request Bodyrequired”object
object
Stable document id. Supply it to make index idempotent (re-indexing the same id replaces the document); generated when omitted.
The document text indexed for search.
Document type (e.g. the WordPress post type).
Canonical URL for the document.
ISO 639-1 language code.
Free-form metadata; values are stored as keywords for exact-match filtering.
object
Example
{ "status": "publish", "category": "news", "tags": [ "guide", "billing" ]}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.
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
Lowercase tag name, such as a, img, iframe or embed.
How many times the element occurs in the document.
Link URL.
Source URL.
Lowercase host of the URL.
Lowercase URL scheme, such as https or mailto.
Whether the URL had a query string.
Whether the URL points at the site itself.
Link target, such as _blank.
Link rel tokens, lowercase.
Image alt text. An empty string means the attribute is present without text; omitted means the attribute is missing.
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
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
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
object
Whole numbers between -2^53 and 2^53.
object
Example
{ "tag": "a", "count": 2, "href": "https://example.org/page", "domain": "example.org", "scheme": "https", "has_query": true, "internal": false, "target": "_blank", "rel": [ "nofollow", "noopener" ]}True when the client dropped elements to stay within its limits, so the list is incomplete.
Responses
Section titled “Responses”Per-document results, including any per-item failures
object
object
HTTP-style status for this item (e.g. 201, 200, 400).
Failure reason, present only when the item failed.
Example
{ "items": [ { "result": "created" } ]}Invalid request body or parameters. On agent create and update, error type “profile_unavailable” means the requested profile is not available to the caller.
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}Missing or invalid bearer token
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}Headers
Section titled “Headers”Example
Bearer realm="ai-services"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.
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}The requested resource was not found
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}Request body exceeds the 64 KiB limit
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}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.
The knowledge base is not currently available. Retry after a short delay.
object
object
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.
Where the customer can resolve the error, set on an entitlement_required refusal that has an error_code when one is configured.
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.
Example
{ "error": { "type": "invalid_request_error", "request_id": "80f1e2c3a4b5c6d7e8f9a0b1c2d3e4f5" }}