# Managing Elevated Site Search with Your AI Agent (agent documentation)

> Machine-readable documentation for AI agents. Human version: https://elevatedextensions.com/documentation/site-search/managing-with-ai-agent/

This is the complete machine-readable reference for the 14 `elevated-site-search/*` abilities in Elevated Site Search. Every schema below is served verbatim from the ability registry (the same schemas the MCP server and the REST surface enforce), and every example is a real captured response.

## Calling conventions

Two equivalent surfaces, one registry:

- **MCP**: connect to `/wp-json/mcp/mcp-adapter-default-server` (MCP Streamable HTTP). Each ability is exposed as an MCP tool with the same name. Pass the input object as the tool arguments.
- **REST**: `/wp-json/wp-abilities/v1/abilities/{ability-name}/run`, authenticated as an administrator (use an application password). The HTTP method is enforced from the ability's annotations:

| Annotations | Method | Where the input goes |
|---|---|---|
| `readonly: true` | GET | `input` query parameter, PHP bracket syntax: `?input[query]=test&input[limit]=5` |
| `destructive: true` and `idempotent: true` | DELETE | `input` query parameter |
| everything else | POST | JSON body: `{"input": { ... }}` |

Each ability section below states its resolved method.

`GET /wp-json/wp-abilities/v1/abilities` lists every ability with its full input and output schema; `GET /wp-json/wp-abilities/v1/abilities/{ability-name}` returns one.

Wrong method:

```json
{
 "status": 405,
 "data": {
  "code": "rest_ability_invalid_method",
  "message": "Read-only abilities require GET method.",
  "data": {
   "status": 405
  }
 }
}
```

The other two rejection messages, from the same rule: `"Abilities that perform destructive actions require DELETE method."` and `"Abilities that perform updates require POST method."`

Unauthenticated:

```json
{
 "status": 401,
 "data": {
  "code": "rest_ability_cannot_execute",
  "message": "Sorry, you are not allowed to execute this ability.",
  "data": {
   "status": 401
  }
 }
}
```

Input is validated against the schema before any handler runs. Unknown keys are rejected, not ignored, and every rejection names the valid values (see the error catalog at the end).

**Agent access switch.** The site owner can turn agent access off (Site Search settings, stored as option `elevated_site_search_agent_access` = `"no"`). While off, the abilities are not registered and every call fails with:

```json
{
 "status": 404,
 "error": {
  "code": "rest_ability_not_found",
  "message": "Ability not found."
 }
}
```

Only a human can switch access back on; do not retry, ask the site owner.

**Mutations are serialized behind a mutex.** A concurrent settings or index operation fails with `Another settings or index operation is already in progress.` Poll `get-rebuild-progress` to a terminal status before the next mutation.

## The settings object

One settings object backs `get-settings` and `update-settings`. It has 169 properties. A `get-settings` response always contains the 125 required keys; the 44 per-side border, radius, and padding override keys appear only when they are set. In an `update-settings` patch those same 44 keys additionally accept `null`, which clears the per-side override so the shorthand key applies again. The 44 keys:

`inputBorderRadiusBL, inputBorderRadiusBR, inputBorderRadiusTL, inputBorderRadiusTR, inputBorderWidthBottom, inputBorderWidthLeft, inputBorderWidthRight, inputBorderWidthTop, inputPaddingBottom, inputPaddingLeft, inputPaddingRight, inputPaddingTop, pillBorderRadiusBL, pillBorderRadiusBR, pillBorderRadiusTL, pillBorderRadiusTR, pillBorderWidthBottom, pillBorderWidthLeft, pillBorderWidthRight, pillBorderWidthTop, resultImageBorderRadiusBL, resultImageBorderRadiusBR, resultImageBorderRadiusTL, resultImageBorderRadiusTR, resultImageBorderWidthBottom, resultImageBorderWidthLeft, resultImageBorderWidthRight, resultImageBorderWidthTop, resultItemBorderRadiusBL, resultItemBorderRadiusBR, resultItemBorderRadiusTL, resultItemBorderRadiusTR, resultItemBorderWidthBottom, resultItemBorderWidthLeft, resultItemBorderWidthRight, resultItemBorderWidthTop, resultsBorderRadiusBL, resultsBorderRadiusBR, resultsBorderRadiusTL, resultsBorderRadiusTR, resultsBorderWidthBottom, resultsBorderWidthLeft, resultsBorderWidthRight, resultsBorderWidthTop`

The schema (served by the registry; in update patches, each of the 44 keys above becomes `oneOf [the schema shown here, null]`):

```json
{
 "type": "object",
 "properties": {
  "minChars": {
   "type": "integer",
   "minimum": 1,
   "maximum": 5
  },
  "maxInputWidth": {
   "type": "string",
   "pattern": "^(?:[2-9][0-9]{2}|1[01][0-9]{2}|1200)px$"
  },
  "maxFormWidth": {
   "type": "string",
   "pattern": "^(?:[2-9][0-9]{2}|1[01][0-9]{2}|1200)px$"
  },
  "breakpoint": {
   "type": "string",
   "pattern": "^(?:[2-9][0-9]{2}|1[0-9]{3}|2000)px$"
  },
  "layout": {
   "type": "string",
   "enum": [
    "search-bar",
    "icon-mobile",
    "icon-only"
   ]
  },
  "desktopLayout": {
   "type": "string",
   "enum": [
    "popover",
    "modal"
   ]
  },
  "showSearchIcon": {
   "type": "boolean"
  },
  "inputBackgroundColor": {
   "type": "string",
   "maxLength": 64
  },
  "inputTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "inputBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "showBorderStyles": {
   "type": "boolean"
  },
  "inputBorderWeight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "inputBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "inputBorderWidthTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "inputBorderWidthRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "inputBorderWidthBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "inputBorderWidthLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "inputBorderRadiusTL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "inputBorderRadiusTR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "inputBorderRadiusBR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "inputBorderRadiusBL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "inputPaddingX": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "inputPaddingY": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "inputPaddingTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "inputPaddingRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "inputPaddingBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "inputPaddingLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "iconPaddingX": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "iconPaddingY": {
   "type": "integer",
   "minimum": 0,
   "maximum": 32
  },
  "iconColor": {
   "type": "string",
   "maxLength": 64
  },
  "inputTextSize": {
   "type": "integer",
   "minimum": 10,
   "maximum": 32
  },
  "maxResults": {
   "type": "integer",
   "minimum": 3,
   "maximum": 20
  },
  "noResultsLabel": {
   "type": "string",
   "maxLength": 200
  },
  "showThumbnails": {
   "type": "boolean"
  },
  "showExcerpts": {
   "type": "boolean"
  },
  "showPostTypeBadge": {
   "type": "boolean"
  },
  "showDate": {
   "type": "boolean"
  },
  "showCategories": {
   "type": "boolean"
  },
  "highlightMatches": {
   "type": "boolean"
  },
  "highlightColor": {
   "type": "string",
   "maxLength": 64
  },
  "highlightTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "excerptWordLimit": {
   "type": "integer",
   "minimum": 5,
   "maximum": 100
  },
  "resultsBackground": {
   "type": "string",
   "maxLength": 64
  },
  "resultHoverBackground": {
   "type": "string",
   "maxLength": 64
  },
  "resultsAreaPadding": {
   "type": "string",
   "maxLength": 32,
   "pattern": "^(0|[0-9]+(?:\\.[0-9]+)?(?:px|rem|em))$"
  },
  "resultsListPadding": {
   "type": "string",
   "maxLength": 32,
   "pattern": "^(0|[0-9]+(?:\\.[0-9]+)?(?:px|rem|em))$"
  },
  "resultTitleSize": {
   "type": "integer",
   "minimum": 8,
   "maximum": 36
  },
  "resultTitleColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultExcerptColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultExcerptSize": {
   "type": "integer",
   "minimum": 8,
   "maximum": 36
  },
  "resultsSectionLabelsColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultsSectionLabelsTextSize": {
   "type": "integer",
   "minimum": 8,
   "maximum": 36
  },
  "showResultsBorderControls": {
   "type": "boolean"
  },
  "resultsBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultsBorderWidth": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultsBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "resultsBorderWidthTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultsBorderWidthRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultsBorderWidthBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultsBorderWidthLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultsBorderRadiusTL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "resultsBorderRadiusTR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "resultsBorderRadiusBR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "resultsBorderRadiusBL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "resultItemBorder": {
   "type": "boolean"
  },
  "resultItemBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultItemBorderWidth": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultItemBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultItemBorderWidthTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultItemBorderWidthRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultItemBorderWidthBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultItemBorderWidthLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultItemBorderRadiusTL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultItemBorderRadiusTR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultItemBorderRadiusBR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultItemBorderRadiusBL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultImageBorder": {
   "type": "boolean"
  },
  "resultImageBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "resultImageBorderWidth": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultImageBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultImageBorderWidthTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultImageBorderWidthRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultImageBorderWidthBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultImageBorderWidthLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "resultImageBorderRadiusTL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultImageBorderRadiusTR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultImageBorderRadiusBR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "resultImageBorderRadiusBL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 16
  },
  "searchInContent": {
   "type": "boolean"
  },
  "searchInExcerpt": {
   "type": "boolean"
  },
  "searchInTaxonomies": {
   "type": "boolean"
  },
  "searchInComments": {
   "type": "boolean"
  },
  "searchInCustomFields": {
   "type": "array",
   "maxItems": 100,
   "uniqueItems": true,
   "items": {
    "type": "string",
    "maxLength": 191
   }
  },
  "indexPostTypes": {
   "type": "array",
   "minItems": 1,
   "maxItems": 32,
   "uniqueItems": true,
   "items": {
    "type": "string"
   }
  },
  "useCustomFieldWeights": {
   "type": "boolean"
  },
  "fieldWeights": {
   "type": "object",
   "properties": {
    "title": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    },
    "content": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    },
    "excerpt": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    },
    "taxonomies": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    },
    "customFields": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    },
    "comments": {
     "type": "integer",
     "minimum": 1,
     "maximum": 10
    }
   },
   "required": [
    "title",
    "content",
    "excerpt",
    "taxonomies",
    "customFields",
    "comments"
   ],
   "additionalProperties": false
  },
  "fuzzyMatching": {
   "type": "string",
   "enum": [
    "off",
    "soft",
    "normal",
    "hard"
   ]
  },
  "includeExcludeMode": {
   "type": "string",
   "enum": [
    "all",
    "include",
    "exclude"
   ]
  },
  "filters": {
   "type": "array",
   "maxItems": 100,
   "items": {
    "type": "object",
    "properties": {
     "type": {
      "type": "string",
      "enum": [
       "categories",
       "tags"
      ]
     },
     "value": {
      "type": "string",
      "maxLength": 200
     }
    },
    "required": [
     "type",
     "value"
    ],
    "additionalProperties": false
   }
  },
  "searchEngine": {
   "type": "string",
   "enum": [
    "sqlite",
    "mysql"
   ]
  },
  "indexSchedule": {
   "type": "boolean"
  },
  "indexInterval": {
   "type": "string",
   "enum": [
    "daily",
    "weekly",
    "monthly"
   ]
  },
  "indexTime": {
   "type": "string",
   "pattern": "^(?:[01][0-9]|2[0-3]):[0-5][0-9]$"
  },
  "enableDebugMode": {
   "type": "boolean"
  },
  "enableKeyboardShortcuts": {
   "type": "boolean"
  },
  "keyboardShortcutKey": {
   "type": "string",
   "enum": [
    "cmdK",
    "slash",
    "both"
   ]
  },
  "showKeyboardHints": {
   "type": "boolean"
  },
  "theme": {
   "type": "string",
   "enum": [
    "classic",
    "modern"
   ]
  },
  "showPopularSearches": {
   "type": "boolean"
  },
  "showRecentSearches": {
   "type": "boolean"
  },
  "recentSearchesCount": {
   "type": "integer",
   "minimum": 1,
   "maximum": 10
  },
  "popularSearchesCount": {
   "type": "integer",
   "minimum": 1,
   "maximum": 10
  },
  "groupResultsByType": {
   "type": "boolean"
  },
  "showDidYouMean": {
   "type": "boolean"
  },
  "showPostTypeFilter": {
   "type": "boolean"
  },
  "pillBackground": {
   "type": "string",
   "maxLength": 64
  },
  "pillHoverBackground": {
   "type": "string",
   "maxLength": 64
  },
  "pillActiveBackground": {
   "type": "string",
   "maxLength": 64
  },
  "pillTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "pillHoverTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "pillActiveTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "pillTextSize": {
   "type": "integer",
   "minimum": 8,
   "maximum": 20
  },
  "pillBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 50
  },
  "showPillBorderControls": {
   "type": "boolean"
  },
  "pillBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "pillBorderWidth": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "pillBorderRadiusTL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 50
  },
  "pillBorderRadiusTR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 50
  },
  "pillBorderRadiusBR": {
   "type": "integer",
   "minimum": 0,
   "maximum": 50
  },
  "pillBorderRadiusBL": {
   "type": "integer",
   "minimum": 0,
   "maximum": 50
  },
  "pillBorderWidthTop": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "pillBorderWidthRight": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "pillBorderWidthBottom": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "pillBorderWidthLeft": {
   "type": "integer",
   "minimum": 0,
   "maximum": 10
  },
  "brandColor": {
   "type": "string",
   "maxLength": 64
  },
  "accentColor": {
   "type": "string",
   "maxLength": 64
  },
  "backgroundColor": {
   "type": "string",
   "maxLength": 64
  },
  "surfaceColor": {
   "type": "string",
   "maxLength": 64
  },
  "overrideThemeColors": {
   "type": "boolean"
  },
  "badgeBackground": {
   "type": "string",
   "maxLength": 64
  },
  "badgeTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "badgeTextSize": {
   "type": "integer",
   "minimum": 8,
   "maximum": 20
  },
  "badgeBorderRadius": {
   "type": "integer",
   "minimum": 0,
   "maximum": 24
  },
  "overrideInputColors": {
   "type": "boolean"
  },
  "overrideResultColors": {
   "type": "boolean"
  },
  "themeMode": {
   "type": "string",
   "enum": [
    "light",
    "dark",
    "custom"
   ]
  },
  "modalTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "modalMutedTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "modalBorderColor": {
   "type": "string",
   "maxLength": 64
  },
  "modalSurfaceColor": {
   "type": "string",
   "maxLength": 64
  },
  "modalAccentColor": {
   "type": "string",
   "maxLength": 64
  },
  "sectionLabelColor": {
   "type": "string",
   "maxLength": 64
  },
  "itemTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "kbdPillBackground": {
   "type": "string",
   "maxLength": 64
  },
  "kbdPillTextColor": {
   "type": "string",
   "maxLength": 64
  },
  "placeholderColor": {
   "type": "string",
   "maxLength": 64
  },
  "overlayColor": {
   "type": "string",
   "maxLength": 64
  },
  "recentSearchesLabel": {
   "type": "string",
   "maxLength": 200
  },
  "popularSearchesLabel": {
   "type": "string",
   "maxLength": 200
  },
  "clearRecentLabel": {
   "type": "string",
   "maxLength": 200
  },
  "emptySearchLabel": {
   "type": "string",
   "maxLength": 200
  },
  "didYouMeanLabel": {
   "type": "string",
   "maxLength": 200
  },
  "navigateHintLabel": {
   "type": "string",
   "maxLength": 200
  },
  "openHintLabel": {
   "type": "string",
   "maxLength": 200
  },
  "closeHintLabel": {
   "type": "string",
   "maxLength": 200
  },
  "categoriesLabel": {
   "type": "string",
   "maxLength": 200
  },
  "resultsStatsPattern": {
   "type": "string",
   "maxLength": 200
  },
  "showPoweredBy": {
   "type": "boolean"
  },
  "affiliateId": {
   "type": "string",
   "pattern": "^(?:[A-Za-z0-9_-]{1,64})?$"
  }
 },
 "required": [
  "minChars",
  "maxInputWidth",
  "maxFormWidth",
  "breakpoint",
  "layout",
  "desktopLayout",
  "showSearchIcon",
  "inputBackgroundColor",
  "inputTextColor",
  "inputBorderColor",
  "showBorderStyles",
  "inputBorderWeight",
  "inputBorderRadius",
  "inputPaddingX",
  "inputPaddingY",
  "iconPaddingX",
  "iconPaddingY",
  "iconColor",
  "inputTextSize",
  "maxResults",
  "noResultsLabel",
  "showThumbnails",
  "showExcerpts",
  "showPostTypeBadge",
  "showDate",
  "showCategories",
  "highlightMatches",
  "highlightColor",
  "highlightTextColor",
  "excerptWordLimit",
  "resultsBackground",
  "resultHoverBackground",
  "resultsAreaPadding",
  "resultsListPadding",
  "resultTitleSize",
  "resultTitleColor",
  "resultExcerptColor",
  "resultExcerptSize",
  "resultsSectionLabelsColor",
  "resultsSectionLabelsTextSize",
  "showResultsBorderControls",
  "resultsBorderColor",
  "resultsBorderWidth",
  "resultsBorderRadius",
  "resultItemBorder",
  "resultItemBorderColor",
  "resultItemBorderWidth",
  "resultItemBorderRadius",
  "resultImageBorder",
  "resultImageBorderColor",
  "resultImageBorderWidth",
  "resultImageBorderRadius",
  "searchInContent",
  "searchInExcerpt",
  "searchInTaxonomies",
  "searchInComments",
  "searchInCustomFields",
  "indexPostTypes",
  "useCustomFieldWeights",
  "fieldWeights",
  "fuzzyMatching",
  "includeExcludeMode",
  "filters",
  "searchEngine",
  "indexSchedule",
  "indexInterval",
  "indexTime",
  "enableDebugMode",
  "enableKeyboardShortcuts",
  "keyboardShortcutKey",
  "showKeyboardHints",
  "theme",
  "showPopularSearches",
  "showRecentSearches",
  "recentSearchesCount",
  "popularSearchesCount",
  "groupResultsByType",
  "showDidYouMean",
  "showPostTypeFilter",
  "pillBackground",
  "pillHoverBackground",
  "pillActiveBackground",
  "pillTextColor",
  "pillHoverTextColor",
  "pillActiveTextColor",
  "pillTextSize",
  "pillBorderRadius",
  "showPillBorderControls",
  "pillBorderColor",
  "pillBorderWidth",
  "brandColor",
  "accentColor",
  "backgroundColor",
  "surfaceColor",
  "overrideThemeColors",
  "badgeBackground",
  "badgeTextColor",
  "badgeTextSize",
  "badgeBorderRadius",
  "overrideInputColors",
  "overrideResultColors",
  "themeMode",
  "modalTextColor",
  "modalMutedTextColor",
  "modalBorderColor",
  "modalSurfaceColor",
  "modalAccentColor",
  "sectionLabelColor",
  "itemTextColor",
  "kbdPillBackground",
  "kbdPillTextColor",
  "placeholderColor",
  "overlayColor",
  "recentSearchesLabel",
  "popularSearchesLabel",
  "clearRecentLabel",
  "emptySearchLabel",
  "didYouMeanLabel",
  "navigateHintLabel",
  "openHintLabel",
  "closeHintLabel",
  "categoriesLabel",
  "resultsStatsPattern",
  "showPoweredBy",
  "affiliateId"
 ],
 "additionalProperties": false
}
```

## Abilities

### `elevated-site-search/get-settings`

Retrieves the current Elevated Site Search settings. Annotations: readonly, idempotent. REST method: GET.

The response fills every shipped default, so read it once before patching: it is the authoritative current state.

Input schema:

```json
{
 "type": "object",
 "properties": [],
 "additionalProperties": false,
 "default": {}
}
```

Output schema: the `settings` value is the settings object above.

```json
{
 "type": "object",
 "properties": {
  "settings": "<the 169-property settings object: see The settings object above>"
 },
 "additionalProperties": false,
 "required": [
  "settings"
 ]
}
```

**Example: read the current settings**

Input:

```json
{}
```

Response:

```json
{
 "settings": {
  "minChars": 3,
  "maxInputWidth": "600px",
  "maxFormWidth": "600px",
  "breakpoint": "768px",
  "layout": "search-bar",
  "desktopLayout": "popover",
  "showSearchIcon": true,
  "inputBackgroundColor": "",
  "inputTextColor": "",
  "inputBorderColor": "",
  "showBorderStyles": false,
  "inputBorderWeight": 1,
  "inputBorderRadius": 8,
  "inputPaddingX": 12,
  "inputPaddingY": 10,
  "iconPaddingX": 12,
  "iconPaddingY": 12,
  "iconColor": "",
  "inputTextSize": 16,
  "maxResults": 12,
  "noResultsLabel": "No results found",
  "showThumbnails": true,
  "showExcerpts": true,
  "showPostTypeBadge": true,
  "showDate": false,
  "showCategories": false,
  "highlightMatches": true,
  "highlightColor": "",
  "highlightTextColor": "",
  "excerptWordLimit": 20,
  "resultsBackground": "#ffffff",
  "resultHoverBackground": "",
  "resultsAreaPadding": "14px",
  "resultsListPadding": "0",
  "resultTitleSize": 16,
  "resultTitleColor": "",
  "resultExcerptColor": "",
  "resultExcerptSize": 12,
  "resultsSectionLabelsColor": "",
  "resultsSectionLabelsTextSize": 14,
  "showResultsBorderControls": false,
  "resultsBorderColor": "hsl(var(--border))",
  "resultsBorderWidth": 0,
  "resultsBorderRadius": 16,
  "resultItemBorder": false,
  "resultItemBorderColor": "hsl(var(--border))",
  "resultItemBorderWidth": 0,
  "resultItemBorderRadius": 8,
  "resultImageBorder": false,
  "resultImageBorderColor": "hsl(var(--border))",
  "resultImageBorderWidth": 0,
  "resultImageBorderRadius": 10,
  "searchInContent": true,
  "searchInExcerpt": true,
  "searchInTaxonomies": true,
  "searchInComments": false,
  "searchInCustomFields": [],
  "indexPostTypes": [
   "post",
   "page",
   "product"
  ],
  "useCustomFieldWeights": false,
  "fieldWeights": {
   "title": 5,
   "content": 1,
   "excerpt": 2,
   "taxonomies": 2,
   "customFields": 1,
   "comments": 1
  },
  "fuzzyMatching": "normal",
  "includeExcludeMode": "all",
  "filters": [],
  "searchEngine": "mysql",
  "indexSchedule": false,
  "indexInterval": "weekly",
  "indexTime": "03:00",
  "enableDebugMode": false,
  "enableKeyboardShortcuts": true,
  "keyboardShortcutKey": "cmdK",
  "showKeyboardHints": true,
  "theme": "classic",
  "showPopularSearches": true,
  "showRecentSearches": true,
  "recentSearchesCount": 5,
  "popularSearchesCount": 5,
  "groupResultsByType": true,
  "showDidYouMean": true,
  "showPostTypeFilter": true,
  "pillBackground": "",
  "pillHoverBackground": "",
  "pillActiveBackground": "",
  "pillTextColor": "",
  "pillHoverTextColor": "",
  "pillActiveTextColor": "",
  "pillTextSize": 12,
  "pillBorderRadius": 20,
  "showPillBorderControls": false,
  "pillBorderColor": "#e2e8f0",
  "pillBorderWidth": 0,
  "brandColor": "#0077c2",
  "accentColor": "#00bfff",
  "backgroundColor": "#ffffff",
  "surfaceColor": "",
  "overrideThemeColors": false,
  "badgeBackground": "",
  "badgeTextColor": "",
  "badgeTextSize": 11,
  "badgeBorderRadius": 10,
  "overrideInputColors": false,
  "overrideResultColors": false,
  "themeMode": "light",
  "modalTextColor": "",
  "modalMutedTextColor": "",
  "modalBorderColor": "",
  "modalSurfaceColor": "",
  "modalAccentColor": "",
  "sectionLabelColor": "",
  "itemTextColor": "",
  "kbdPillBackground": "",
  "kbdPillTextColor": "",
  "placeholderColor": "",
  "overlayColor": "",
  "recentSearchesLabel": "Recent Searches",
  "popularSearchesLabel": "Popular Searches",
  "clearRecentLabel": "Clear",
  "emptySearchLabel": "Start typing to search",
  "didYouMeanLabel": "Did you mean:",
  "navigateHintLabel": "Navigate",
  "openHintLabel": "Open",
  "closeHintLabel": "Close",
  "categoriesLabel": "Categories",
  "resultsStatsPattern": "{total} results in {time}ms",
  "showPoweredBy": false,
  "affiliateId": ""
 }
}
```

### `elevated-site-search/update-settings`

Updates validated Elevated Site Search settings. Annotations: write, destructive, idempotent. REST method: DELETE.

Send only the keys you are changing; the patch merges into stored settings and the response returns the complete resulting settings. Changing scope keys (`indexPostTypes`, `searchInCustomFields`, `searchInTaxonomies`, `searchInComments`, `searchInContent`, `searchInExcerpt`) triggers an index rebuild, reported in `index_rebuilding`, `rebuild_id`, and `rebuild_mode`. Annotated destructive but takes NO `confirm` key; the schema is closed and rejects one. Dark mode needs the pairing the admin UI writes: `themeMode: "dark"` together with `backgroundColor: "#11161c"`; setting `themeMode` alone does not restyle the UI because the palette derives from `backgroundColor`.

Input schema: the `settings` value accepts a partial patch of the settings object above.

```json
{
 "type": "object",
 "properties": {
  "settings": "<partial patch of the settings object above; no key is required; the 44 per-side override keys also accept null>"
 },
 "additionalProperties": false,
 "required": [
  "settings"
 ]
}
```

Output schema: the `settings` value is the settings object above.

```json
{
 "type": "object",
 "properties": {
  "settings": "<the 169-property settings object: see The settings object above>",
  "index_rebuilding": {
   "type": "boolean"
  },
  "rebuild_mode": {
   "type": [
    "string",
    "null"
   ]
  },
  "rebuild_id": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "settings",
  "index_rebuilding",
  "rebuild_mode"
 ]
}
```

**Example: change one setting (the settings object in the response is elided here)**

Input:

```json
{
 "settings": {
  "minChars": 2
 }
}
```

Response:

```json
{
 "settings": "<the full 125-key settings object, elided>",
 "index_rebuilding": false,
 "rebuild_mode": null
}
```

**Example: revert it**

Input:

```json
{
 "settings": {
  "minChars": 3
 }
}
```

Response:

```json
{
 "settings": "<the full 125-key settings object, elided>",
 "index_rebuilding": false,
 "rebuild_mode": null
}
```

**Example: out-of-range value**

Input:

```json
{
 "settings": {
  "minChars": 99
 }
}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/update-settings\" has invalid input. Reason: input[settings][minChars] must be between 1 (inclusive) and 5 (inclusive)"
 }
}
```

**Example: unknown key (closed schema)**

Input:

```json
{
 "settings": {
  "nope": true
 }
}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/update-settings\" has invalid input. Reason: nope is not a valid property of Object."
 }
}
```

**Example: missing settings envelope**

Input:

```json
{}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/update-settings\" has invalid input. Reason: settings is a required property of input."
 }
}
```

### `elevated-site-search/reset-settings`

Resets Elevated Site Search settings to their factory defaults. Annotations: write, destructive, idempotent. REST method: DELETE.

Restores shipped defaults and rebuilds the index for the default scope.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "confirm": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "confirm"
 ]
}
```

Output schema: the `settings` value is the settings object above.

```json
{
 "type": "object",
 "properties": {
  "settings": "<the 169-property settings object: see The settings object above>",
  "index_rebuilding": {
   "type": "boolean"
  },
  "rebuild_mode": {
   "type": [
    "string",
    "null"
   ]
  },
  "rebuild_id": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "settings",
  "index_rebuilding",
  "rebuild_mode"
 ]
}
```

**Example: without confirm (fails before any side effect)**

Input:

```json
{}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/reset-settings\" has invalid input. Reason: confirm is a required property of input."
 }
}
```

### `elevated-site-search/search-site`

Searches indexed site content using Elevated Site Search. Annotations: readonly, idempotent. REST method: GET.

Lean by design: `thumbnail` is always null, `url` is the permalink shortform `/?p=N`, `categories` is empty, and `<mark>` wraps matches in title and excerpt. Searches made through this ability are not recorded in analytics (the tracker only runs on visitor searches).

Input schema:

```json
{
 "type": "object",
 "properties": {
  "query": {
   "type": "string",
   "maxLength": 200
  },
  "limit": {
   "type": "integer",
   "minimum": 1,
   "maximum": 20,
   "default": 10
  },
  "offset": {
   "type": "integer",
   "minimum": 0,
   "maximum": 500,
   "default": 0
  },
  "post_type": {
   "type": "string",
   "maxLength": 64,
   "default": ""
  }
 },
 "additionalProperties": false,
 "required": [
  "query"
 ]
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "results": {
   "type": "array",
   "items": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer"
     },
     "title": {
      "type": "string"
     },
     "excerpt": {
      "type": "string"
     },
     "url": {
      "type": "string"
     },
     "type": {
      "type": "string"
     },
     "typeLabel": {
      "type": "string"
     },
     "thumbnail": {
      "type": [
       "string",
       "null"
      ]
     },
     "date": {
      "type": "string"
     },
     "categories": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "id": {
         "type": "integer"
        },
        "name": {
         "type": "string"
        },
        "url": {
         "type": "string"
        }
       },
       "additionalProperties": false,
       "required": [
        "id",
        "name",
        "url"
       ]
      }
     }
    },
    "additionalProperties": false,
    "required": [
     "id",
     "title",
     "excerpt",
     "url",
     "type",
     "typeLabel",
     "thumbnail",
     "date",
     "categories"
    ]
   }
  },
  "categories": {
   "type": "array",
   "items": {
    "type": "object",
    "properties": {
     "id": {
      "type": "integer"
     },
     "name": {
      "type": "string"
     },
     "type": {
      "type": "string"
     },
     "count": {
      "type": "integer"
     },
     "url": {
      "type": "string"
     }
    },
    "additionalProperties": false,
    "required": [
     "id",
     "name",
     "type",
     "count",
     "url"
    ]
   }
  },
  "total": {
   "type": "integer"
  },
  "typeBreakdown": {
   "type": "object",
   "additionalProperties": {
    "type": "integer"
   }
  },
  "suggestion": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "results",
  "categories",
  "total",
  "typeBreakdown",
  "suggestion"
 ]
}
```

**Example: simple search**

Input:

```json
{
 "query": "test"
}
```

Response:

```json
{
 "results": [
  {
   "id": 157,
   "title": "<mark>Test</mark>",
   "excerpt": "",
   "url": "/?p=157",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2025-10-22 23:21:24",
   "categories": []
  },
  {
   "id": 162,
   "title": "<mark>Test</mark> 2",
   "excerpt": "",
   "url": "/?p=162",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2025-11-02 01:04:53",
   "categories": []
  },
  {
   "id": 207,
   "title": "<mark>test</mark> again",
   "excerpt": "",
   "url": "/?p=207",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2025-12-06 12:45:17",
   "categories": []
  },
  {
   "id": 2376,
   "title": "Breakdance <mark>Test</mark>",
   "excerpt": "",
   "url": "/?p=2376",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2026-02-14 17:17:46",
   "categories": []
  },
  {
   "id": 6879,
   "title": "<mark>Test</mark> Dress",
   "excerpt": "A simple lined <mark>test</mark>-fit dress used by our studio for sizing sessions.",
   "url": "/?p=6879",
   "type": "product",
   "typeLabel": "Product",
   "thumbnail": null,
   "date": "2026-05-28 04:06:47",
   "categories": []
  },
  {
   "id": 8899,
   "title": "EAA <mark>Test</mark> Standalone",
   "excerpt": "[elevated_address_autocomplete label=&quot;Delivery address&quot; map=&quot;true&quot;]",
   "url": "/?p=8899",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2026-07-12 18:37:37",
   "categories": []
  },
  {
   "id": 2409,
   "title": "<mark>Test</mark>ing 1.0.2",
   "excerpt": "",
   "url": "/?p=2409",
   "type": "page",
   "typeLabel": "Page",
   "thumbnail": null,
   "date": "2026-03-15 17:09:06",
   "categories": []
  },
  {
   "id": 188,
   "title": "Free 2",
   "excerpt": "",
   "url": "/?p=188",
   "type": "product",
   "typeLabel": "Product",
   "thumbnail": null,
   "date": "2025-11-30 18:38:20",
   "categories": []
  },
  {
   "id": 9152,
   "title": "Behind the Seams: How We Source Sustainable Fabrics",
   "excerpt": "Every Zalya piece starts with a fabric decision, and we make that decision against three questions: how it is grown,...",
   "url": "/?p=9152",
   "type": "post",
   "typeLabel": "Post",
   "thumbnail": null,
   "date": "2026-08-25 23:02:41",
   "categories": []
  }
 ],
 "categories": [],
 "total": 9,
 "typeBreakdown": {
  "page": 6,
  "product": 2,
  "post": 1
 },
 "suggestion": null
}
```

**Example: with a limit**

Input:

```json
{
 "query": "the",
 "limit": 2
}
```

Response:

```json
{
 "results": [
  {
   "id": 9148,
   "title": "<mark>The</mark> Complete Guide to Layering Jackets This Winter",
   "excerpt": "Layering is a system, not a pile. <mark>The</mark> rule of three keeps it simple: a base layer that brea<mark>the</mark>s, a...",
   "url": "/?p=9148",
   "type": "post",
   "typeLabel": "Post",
   "thumbnail": null,
   "date": "2026-08-25 23:02:40",
   "categories": []
  },
  {
   "id": 9152,
   "title": "Behind <mark>the</mark> Seams: How We Source Sustainable Fabrics",
   "excerpt": "Every Zalya piece starts with a fabric decision, and we make that decision against three questions: how it is grown,...",
   "url": "/?p=9152",
   "type": "post",
   "typeLabel": "Post",
   "thumbnail": null,
   "date": "2026-08-25 23:02:41",
   "categories": []
  }
 ],
 "categories": [],
 "total": 10,
 "typeBreakdown": {
  "page": 1,
  "product": 1,
  "post": 8
 },
 "suggestion": null
}
```

**Example: query over 200 characters**

Input:

```json
{
 "query": "a...a (201 chars)"
}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/search-site\" has invalid input. Reason: input[query] must be at most 200 characters long."
 }
}
```

**Matching behaviour**

`search-site` resolves each keyword through two wordlist lookups, in order.

1. Prefix match. Every indexed term starting with the keyword, ordered by hit count, capped at 50 expansions. A keyword matches words it is a prefix of.
2. Suffix truncation. Added in 1.1.1. Runs only when the prefix match returned nothing. The keyword is shortened from the right and the prefix match is retried once against the shortened form.

The second lookup exists because prefix matching only works left to right. Languages that inflect by adding endings put the grammar on the end of the word, so the visitor types the longer form and the prefix lookup returns nothing: a product titled `polo` is not reached by typing `polokat`.

Shortening is bounded by two constants:

```
MIN_STEM = 4   never shorten below this many characters
MAX_TRIM = 5   never remove more than this many characters

floor = max(MIN_STEM, length - MAX_TRIM)
stem  = floor < 1 || length <= floor ? null : substring(keyword, 0, floor)
```

The keyword is lowercased first and the substring is multibyte-safe. A keyword of four characters or fewer has no stem, so no retry happens. Both constants are filterable through `elevated_site_search_min_stem_length` and `elevated_site_search_max_suffix_trim`, each receiving the keyword as the second argument.

Stems for representative keywords:

| keyword | length | stem |
|---|---|---|
| `abc` | 3 | none |
| `test` | 4 | none |
| `tests` | 5 | `test` |
| `coffee` | 6 | `coff` |
| `testing` | 7 | `test` |
| `polokat` | 7 | `polo` |
| `MANDHELING` | 10 | `mandh` |
| `Yirgacheffe` | 11 | `yirgac` |

Two conditions gate the retry. Both must hold:

1. The prefix match returned zero rows.
2. `fuzzyMatching` is not `off`, and the query is not a quoted phrase.

The second condition exists because shortening a keyword is a relaxation like any other, and `off` means exact matches only. Quoting a phrase switches fuzziness off for that query, so a quoted keyword never stems. Quoting a term that matches exactly still returns it.

Because the retry runs only after the first lookup came back empty, it can turn a search with no results into a search with results, and it can never change the results of a search that already works.

**Results reached through a stem are not highlighted.** Highlighting wraps the typed keyword where it appears in the title and excerpt. A stem match means the typed keyword is not present in the text, so no `<mark>` is emitted. The pair of examples below shows the same two documents with and without highlighting for that reason.

**Example: a keyword with an ending, fuzziness normal**

The indexed term is `yirgacheffe`. Nothing starts with `yirgacheffes`, so the prefix match returns nothing and the stem `yirgach` is retried.

Input:

```json
{
 "query": "Yirgacheffes",
 "limit": 3
}
```

Response:

```json
{
    "results": [
        {
            "id": 46,
            "title": "A Field Guide to Ethiopian Coffee",
            "excerpt": "Yirgacheffe, Sidamo, Guji and Harrar, and why the names keep moving.",
            "url": "/?p=46",
            "type": "post",
            "typeLabel": "Post",
            "thumbnail": null,
            "date": "2026-06-30 14:25:00",
            "categories": []
        },
        {
            "id": 19,
            "title": "Ethiopia Yirgacheffe",
            "excerpt": "A floral, tea-like cup from the Gedeo zone, picked at the top of the season.",
            "url": "/?p=19",
            "type": "product",
            "typeLabel": "Product",
            "thumbnail": null,
            "date": "2026-09-20 00:00:03",
            "categories": []
        }
    ],
    "categories": [],
    "total": 2,
    "typeBreakdown": {
        "product": 1,
        "post": 1
    },
    "suggestion": null
}
```

**Example: the same keyword without the ending**

The prefix match succeeds, so no retry runs. The same two documents are returned, highlighted, in a different order.

Input:

```json
{
 "query": "Yirgacheffe",
 "limit": 3
}
```

Response:

```json
{
    "results": [
        {
            "id": 19,
            "title": "Ethiopia <mark>Yirgacheffe</mark>",
            "excerpt": "A floral, tea-like cup from the Gedeo zone, picked at the top of the season.",
            "url": "/?p=19",
            "type": "product",
            "typeLabel": "Product",
            "thumbnail": null,
            "date": "2026-09-20 00:00:03",
            "categories": []
        },
        {
            "id": 46,
            "title": "A Field Guide to Ethiopian Coffee",
            "excerpt": "<mark>Yirgacheffe</mark>, Sidamo, Guji and Harrar, and why the names keep moving.",
            "url": "/?p=46",
            "type": "post",
            "typeLabel": "Post",
            "thumbnail": null,
            "date": "2026-06-30 14:25:00",
            "categories": []
        }
    ],
    "categories": [],
    "total": 2,
    "typeBreakdown": {
        "product": 1,
        "post": 1
    },
    "suggestion": null
}
```

**Example: keyword with an ending, fuzziness off**

Condition 2 fails, so no retry runs and the search returns nothing. Note that `typeBreakdown` serializes as an empty array rather than an empty object when there are no results, although the output schema declares it an object. Handle both shapes.

Input:

```json
{
 "query": "Yirgacheffes",
 "limit": 3
}
```

Response:

```json
{
    "results": [],
    "categories": [],
    "total": 0,
    "typeBreakdown": [],
    "suggestion": null
}
```

Searching `Yirgacheffe` without the ending returns the same two results with `fuzzyMatching` set to `off`, which is the invariant above: the retry does not affect a search that already works.

**Totals across the four relevant queries**, with `fuzzyMatching` at `normal`:

| query | total |
|---|---|
| `Yirgacheffes` | 2 |
| `"Yirgacheffes"` | 0 |
| `Yirgacheffe` | 2 |
| `"Yirgacheffe"` | 2 |

Quoting suppresses the retry without suppressing an exact match.

`fuzzyMatching` is a query-side setting. Writing it returns `index_rebuilding: false` and does not schedule a rebuild.

All responses above were captured on an index of 41 documents covering `post`, `page` and `product`, on the `mysql` engine.


### `elevated-site-search/get-index-status`

Retrieves the current search index status. Annotations: readonly, idempotent. REST method: GET.

Input schema:

```json
{
 "type": "object",
 "properties": [],
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "index_exists": {
   "type": "boolean"
  },
  "indexed_posts": {
   "type": "integer"
  },
  "post_types": {
   "type": "array",
   "items": {
    "type": "string"
   }
  },
  "last_rebuild": {
   "type": [
    "string",
    "null"
   ]
  },
  "is_rebuilding": {
   "type": "boolean"
  },
  "engine": {
   "type": "string"
  },
  "target_engine": {
   "type": [
    "string",
    "null"
   ]
  },
  "rebuild_id": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "index_exists",
  "indexed_posts",
  "post_types",
  "last_rebuild",
  "is_rebuilding",
  "engine",
  "target_engine",
  "rebuild_id"
 ]
}
```

**Example: current status**

Input:

```json
{}
```

Response:

```json
{
 "index_exists": true,
 "indexed_posts": 83,
 "post_types": [
  "post",
  "page",
  "product"
 ],
 "last_rebuild": "2026-08-26 00:12:20",
 "is_rebuilding": false,
 "engine": "mysql",
 "target_engine": null,
 "rebuild_id": null
}
```

### `elevated-site-search/rebuild-index`

Starts a rebuild of the Elevated Site Search index. Annotations: write, destructive, not idempotent. REST method: POST.

Drops and rebuilds the index; `engine` switches the storage engine as part of the rebuild. On small sites the rebuild completes inside the call and the response says so (`state: "complete"`); on larger sites poll `get-rebuild-progress` with the returned `rebuild_id` until a terminal status.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "engine": {
   "type": "string",
   "enum": [
    "sqlite",
    "mysql"
   ]
  },
  "confirm": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "confirm"
 ]
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "state": {
   "type": "string",
   "enum": [
    "operation_in_progress",
    "processing",
    "complete",
    "error"
   ]
  },
  "rebuild_id": {
   "type": "string"
  },
  "target_engine": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "state",
  "rebuild_id",
  "target_engine"
 ]
}
```

**Example: without confirm (fails before any side effect)**

Input:

```json
{}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/rebuild-index\" has invalid input. Reason: confirm is a required property of input."
 }
}
```

**Example: confirmed rebuild, completed inside the call**

Input:

```json
{
 "confirm": true
}
```

Response:

```json
{
 "state": "complete",
 "rebuild_id": "f871aee2-fd0a-40ba-8b67-11cfd379d3bc",
 "target_engine": "mysql"
}
```

### `elevated-site-search/get-rebuild-progress`

Retrieves progress for the active search index rebuild. Annotations: readonly, idempotent. REST method: GET.

`status` reaches `complete`, `failed`, or `cancelled`. If the rebuild completed inside the `rebuild-index` call, the first poll already returns the terminal status.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "rebuild_id": {
   "type": [
    "string",
    "null"
   ],
   "maxLength": 128,
   "default": null
  }
 },
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "status": {
   "type": "string"
  },
  "posts_done": {
   "type": "integer"
  },
  "total_posts": {
   "type": "integer"
  },
  "message": {
   "type": "string"
  },
  "rebuild_id": {
   "type": [
    "string",
    "null"
   ]
  },
  "target_engine": {
   "type": [
    "string",
    "null"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "status",
  "posts_done",
  "total_posts",
  "message",
  "rebuild_id",
  "target_engine"
 ]
}
```

**Example: after the rebuild above**

Input:

```json
{
 "rebuild_id": "f871aee2-fd0a-40ba-8b67-11cfd379d3bc"
}
```

Response:

```json
{
 "status": "complete",
 "posts_done": 83,
 "total_posts": 83,
 "message": "Successfully indexed 83 posts",
 "rebuild_id": "f871aee2-fd0a-40ba-8b67-11cfd379d3bc",
 "target_engine": "mysql"
}
```

### `elevated-site-search/cancel-rebuild`

Cancels an in-progress rebuild of the Elevated Site Search index. Annotations: write, destructive, idempotent. REST method: DELETE.

Get the `rebuild_id` from `rebuild-index`, `get-rebuild-progress`, or `get-index-status`.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "rebuild_id": {
   "type": "string",
   "maxLength": 128,
   "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
  },
  "confirm": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "rebuild_id",
  "confirm"
 ]
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "state": {
   "type": "string",
   "enum": [
    "cancelled",
    "not_found",
    "already_complete"
   ]
  },
  "rebuild_id": {
   "type": "string"
  }
 },
 "additionalProperties": false,
 "required": [
  "state",
  "rebuild_id"
 ]
}
```

**Example: cancelling an already-finished rebuild**

Input:

```json
{
 "rebuild_id": "f871aee2-fd0a-40ba-8b67-11cfd379d3bc",
 "confirm": true
}
```

Response:

```json
{
 "state": "already_complete",
 "rebuild_id": "f871aee2-fd0a-40ba-8b67-11cfd379d3bc"
}
```

### `elevated-site-search/get-health`

Retrieves Elevated Site Search health information. Annotations: readonly, idempotent. REST method: GET.

Input schema:

```json
{
 "type": "object",
 "properties": [],
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "status": {
   "type": "string"
  },
  "engine": {
   "type": "string"
  },
  "index_exists": {
   "type": "boolean"
  },
  "document_count": {
   "type": "integer"
  }
 },
 "additionalProperties": false,
 "required": [
  "status",
  "engine",
  "index_exists",
  "document_count"
 ]
}
```

**Example: after the rebuild above**

Input:

```json
{}
```

Response:

```json
{
 "status": "ok",
 "engine": "mysql",
 "index_exists": true,
 "document_count": 83
}
```

### `elevated-site-search/list-indexable-post-types`

Lists post types available to the search index. Annotations: readonly, idempotent. REST method: GET.

Input schema:

```json
{
 "type": "object",
 "properties": [],
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "items": {
   "type": "array",
   "items": {
    "type": "object",
    "properties": {
     "name": {
      "type": "string"
     },
     "label": {
      "type": "string"
     },
     "count": {
      "type": "integer"
     }
    },
    "additionalProperties": false,
    "required": [
     "name",
     "label",
     "count"
    ]
   }
  }
 },
 "additionalProperties": false,
 "required": [
  "items"
 ]
}
```

**Example:**

Input:

```json
{}
```

Response:

```json
{
 "items": [
  {
   "name": "post",
   "label": "Post",
   "count": 8
  },
  {
   "name": "page",
   "label": "Page",
   "count": 32
  },
  {
   "name": "doc",
   "label": "Doc",
   "count": 247
  },
  {
   "name": "hook",
   "label": "Hook",
   "count": 201
  },
  {
   "name": "snippet",
   "label": "Snippet",
   "count": 117
  },
  {
   "name": "product",
   "label": "Product",
   "count": 43
  }
 ]
}
```

### `elevated-site-search/list-searchable-custom-fields`

Lists custom fields available to the search index. Annotations: readonly, idempotent. REST method: GET.

Cursor pagination: pass `cursor` from the previous response while `has_more` is true.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "search": {
   "type": "string",
   "maxLength": 100,
   "default": ""
  },
  "cursor": {
   "type": [
    "string",
    "null"
   ],
   "maxLength": 128,
   "default": null
  },
  "per_page": {
   "type": "integer",
   "minimum": 1,
   "maximum": 50,
   "default": 50
  }
 },
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "items": {
   "type": "array",
   "items": {
    "type": "string"
   }
  },
  "next_cursor": {
   "type": [
    "string",
    "null"
   ]
  },
  "has_more": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "items",
  "next_cursor",
  "has_more"
 ]
}
```

**Example: first page**

Input:

```json
{}
```

Response:

```json
{
 "items": [
  "abc",
  "allowCombine",
  "appliesTo",
  "attribute_pa_brands",
  "attribute_pa_material",
  "availability",
  "cartNotice",
  "checkboxtest",
  "checkboxtest_copy",
  "discountCalculationType",
  "discountType",
  "discountValue",
  "enable",
  "enableSaleBadge",
  "fixedPrice",
  "freeProductsGiven",
  "freeShippingLabel",
  "giftAddMode",
  "giftSelection",
  "pageContent",
  "paidProductsRequired",
  "productSelection",
  "quantityRequired",
  "rulesIndex",
  "saleBadgeContentClassic",
  "selecttest",
  "tieredTableLocation",
  "tiers",
  "totalSpendRequired",
  "total_sales",
  "wp_dummy_content_generator_attachment"
 ],
 "next_cursor": null,
 "has_more": false
}
```

### `elevated-site-search/find-filter-terms`

Finds taxonomy terms available for search filters. Annotations: readonly, idempotent. REST method: GET.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "taxonomy": {
   "type": "string",
   "enum": [
    "categories",
    "tags",
    "both"
   ],
   "default": "both"
  },
  "search": {
   "type": "string",
   "maxLength": 100,
   "default": ""
  },
  "page": {
   "type": "integer",
   "minimum": 1,
   "maximum": 1000,
   "default": 1
  },
  "per_page": {
   "type": "integer",
   "minimum": 1,
   "maximum": 50,
   "default": 50
  }
 },
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "categories": {
   "type": "object",
   "properties": {
    "items": {
     "type": "array",
     "items": {
      "type": "object",
      "properties": {
       "id": {
        "type": "integer"
       },
       "name": {
        "type": "string"
       },
       "slug": {
        "type": "string"
       },
       "count": {
        "type": "integer"
       }
      },
      "additionalProperties": false,
      "required": [
       "id",
       "name",
       "slug",
       "count"
      ]
     }
    },
    "page": {
     "type": "integer"
    },
    "per_page": {
     "type": "integer"
    },
    "has_more": {
     "type": "boolean"
    }
   },
   "additionalProperties": false,
   "required": [
    "items",
    "page",
    "per_page",
    "has_more"
   ]
  },
  "tags": {
   "type": "object",
   "properties": {
    "items": {
     "type": "array",
     "items": {
      "type": "object",
      "properties": {
       "id": {
        "type": "integer"
       },
       "name": {
        "type": "string"
       },
       "slug": {
        "type": "string"
       },
       "count": {
        "type": "integer"
       }
      },
      "additionalProperties": false,
      "required": [
       "id",
       "name",
       "slug",
       "count"
      ]
     }
    },
    "page": {
     "type": "integer"
    },
    "per_page": {
     "type": "integer"
    },
    "has_more": {
     "type": "boolean"
    }
   },
   "additionalProperties": false,
   "required": [
    "items",
    "page",
    "per_page",
    "has_more"
   ]
  }
 },
 "additionalProperties": false,
 "required": [
  "categories",
  "tags"
 ]
}
```

**Example: categories**

Input:

```json
{
 "taxonomy": "categories"
}
```

Response:

```json
{
 "categories": {
  "items": [
   {
    "id": 318,
    "name": "Care",
    "slug": "care",
    "count": 2
   },
   {
    "id": 38,
    "name": "Clothing",
    "slug": "clothing",
    "count": 0
   },
   {
    "id": 41,
    "name": "Hoodies &amp; Sweatshirts",
    "slug": "hoodies-sweatshirts",
    "count": 0
   },
   {
    "id": 39,
    "name": "Men",
    "slug": "men",
    "count": 0
   },
   {
    "id": 319,
    "name": "News",
    "slug": "news",
    "count": 3
   },
   {
    "id": 317,
    "name": "Style Guides",
    "slug": "style-guides",
    "count": 3
   },
   {
    "id": 40,
    "name": "Tops",
    "slug": "tops",
    "count": 0
   },
   {
    "id": 1,
    "name": "Uncategorized",
    "slug": "uncategorized",
    "count": 0
   },
   {
    "id": 286,
    "name": "Uncategorized",
    "slug": "uncategorized-es",
    "count": 0
   }
  ],
  "page": 1,
  "per_page": 50,
  "has_more": false
 },
 "tags": {
  "items": [],
  "page": 1,
  "per_page": 50,
  "has_more": false
 }
}
```

**Example: invalid taxonomy value (the error names the valid ones)**

Input:

```json
{
 "taxonomy": "category"
}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/find-filter-terms\" has invalid input. Reason: input[taxonomy] is not one of categories, tags, and both."
 }
}
```

### `elevated-site-search/get-popular-searches`

Retrieves popular search query analytics. Annotations: readonly, idempotent. REST method: GET.

Analytics never record queries containing an email address, a run of 5 or more digits, or a phone-like sequence of 7 or more digits, and a query must be searched at least 5 times before it appears in this list. Agent searches via `search-site` are never recorded.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "limit": {
   "type": "integer",
   "minimum": 1,
   "maximum": 10,
   "default": 5
  }
 },
 "additionalProperties": false,
 "default": {}
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "items": {
   "type": "array",
   "items": {
    "type": "object",
    "properties": {
     "query": {
      "type": "string"
     },
     "count": {
      "type": "integer"
     }
    },
    "additionalProperties": false,
    "required": [
     "query",
     "count"
    ]
   }
  }
 },
 "additionalProperties": false,
 "required": [
  "items"
 ]
}
```

**Example:**

Input:

```json
{}
```

Response:

```json
{
 "items": [
  {
   "query": "dress",
   "count": 18
  },
  {
   "query": "denim care",
   "count": 11
  },
  {
   "query": "jackets",
   "count": 7
  },
  {
   "query": "sizing guide",
   "count": 6
  }
 ]
}
```

### `elevated-site-search/clear-popular-searches`

Permanently clears popular search query analytics. Annotations: write, destructive, idempotent. REST method: DELETE.

Input schema:

```json
{
 "type": "object",
 "properties": {
  "confirm": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "confirm"
 ]
}
```

Output schema:

```json
{
 "type": "object",
 "properties": {
  "success": {
   "type": "boolean"
  }
 },
 "additionalProperties": false,
 "required": [
  "success"
 ]
}
```

**Example: without confirm (fails before any side effect)**

Input:

```json
{}
```

Response:

```json
{
 "error": {
  "code": "ability_invalid_input",
  "message": "Ability \"elevated-site-search/clear-popular-searches\" has invalid input. Reason: confirm is a required property of input."
 }
}
```

**Example: confirmed**

Input:

```json
{
 "confirm": true
}
```

Response:

```json
{
 "success": true
}
```

**Example: get-popular-searches afterwards**

Input:

```json
{}
```

Response:

```json
{
 "items": []
}
```

## Error catalog

Every schema failure is a `WP_Error` with code `ability_invalid_input`; the REST surface adds HTTP-level rejections. The messages:

- `Ability "elevated-site-search/search-site" has invalid input. Reason: input[query] must be at most 200 characters long.`
- `Ability "elevated-site-search/find-filter-terms" has invalid input. Reason: input[taxonomy] is not one of categories, tags, and both.`
- `Ability "elevated-site-search/update-settings" has invalid input. Reason: input[settings][minChars] must be between 1 (inclusive) and 5 (inclusive)`
- `Ability "elevated-site-search/update-settings" has invalid input. Reason: nope is not a valid property of Object.`
- `Ability "elevated-site-search/update-settings" has invalid input. Reason: settings is a required property of input.`
- `Ability "elevated-site-search/reset-settings" has invalid input. Reason: confirm is a required property of input.`
- `Ability "elevated-site-search/rebuild-index" has invalid input. Reason: confirm is a required property of input.`
- `Ability "elevated-site-search/clear-popular-searches" has invalid input. Reason: confirm is a required property of input.`
- `405` `Read-only abilities require GET method.` and `Abilities that perform destructive actions require DELETE method.` (REST method mapping)
- `401` `Sorry, you are not allowed to execute this ability.` (unauthenticated)
- `404` `Ability not found.` (agent access switched off by the site owner)
- `Another settings or index operation is already in progress.` (mutex; poll `get-rebuild-progress` to a terminal status, then retry)
