# REST API Endpoints

Complete reference for WP Agentic Writer REST API endpoints.

**Base URL:** `/wp-json/wp-agentic-writer/v1`

**Authentication:** All endpoints require WordPress authentication via `cookie` or application password. Permission checks vary by endpoint (see below).

**Rate Limiting:** Most endpoints are rate-limited. See [Rate Limits](#rate-limits) below.

---

## Rate Limits

| Endpoint | Limit | Window | Notes |
|----------|-------|--------|-------|
| `POST /chat` | 30/min | 60s | |
| `POST /chat_stream` | 30/min | 60s | Streaming variant |
| `POST /search` | 20/min | 60s | Brave Search |
| `POST /fetch-content` | 10/min | 60s | Web content fetch |
| All others | — | — | No rate limiting |

---

## Models

### `GET /models`

List available AI models from OpenRouter.

**Handler:** `Controller_Models::handle_get_models()`

**Permission:** `check_permissions` (authenticated user)

**Response:** Array of model objects from OpenRouter cache.

---

### `POST /models/refresh`

Force-refresh the model cache.

**Handler:** `Controller_Models::handle_refresh_models()`

**Permission:** `check_permissions`

**Response:**
```json
{
  "models": [...],
  "message": "Models refreshed successfully."
}
```

---

## Chat

### `POST /chat`

Send a chat message (non-streaming).

**Handler:** `Controller_Chat::handle_chat_request()`

**Permission:** `check_permissions` + post edit (if `postId` provided)

**Rate Limit:** 30 requests/minute

**Request Body:**
```json
{
  "messages": [...],
  "postId": 123,
  "sessionId": "uuid",
  "type": "planning|writing|revising",
  "stream": false
}
```

**Response:** Full JSON response with assistant message.

---

### `POST /chat` (streaming variant)

Same endpoint with `"stream": true` in request body. Uses Server-Sent Events.

**Rate Limit:** 30 requests/minute (same as non-streaming)

**Response:** `text/event-stream` with chunks.

---

### `POST /clear-context`

Clear the chat context for a post.

**Handler:** `Controller_Chat::handle_clear_context()`

**Permission:** `check_permissions` + post edit

**Request Body:**
```json
{
  "postId": 123,
  "sessionId": "uuid"
}
```

---

### `GET /chat-history/(?P<post_id>\d+)`

Get legacy chat history from post meta. **Deprecated** — use `/conversations` instead.

**Handler:** `Gutenberg_Sidebar::handle_get_chat_history()`

**Permission:** `check_permissions` + post edit

---

## Conversations

### `GET /conversation/(?P<post_id>\d+)`

Get canonical conversation for chat hydration.

**Handler:** `Gutenberg_Sidebar::handle_get_conversation()`

**Permission:** `check_permissions` + post edit

---

### `GET /conversations`

List all conversations for the current user.

**Handler:** `Gutenberg_Sidebar::handle_get_conversations()`

**Permission:** `check_permissions`

---

### `GET /conversations/post/(?P<post_id>\d+)`

List conversations linked to a specific post.

**Handler:** `Gutenberg_Sidebar::handle_get_conversations()`

**Permission:** `check_permissions`

---

### `POST /conversations`

Create a new conversation.

**Handler:** `Gutenberg_Sidebar::handle_create_conversation()`

**Permission:** `check_permissions`

---

### `GET /conversations/(?P<session_id>[a-zA-Z0-9]+)`

Get a specific conversation.

**Handler:** `Gutenberg_Sidebar::handle_get_conversation()`

**Permission:** `check_permissions`

---

### `PUT /conversations/(?P<session_id>[a-zA-Z0-9]+)`

Update conversation metadata.

**Handler:** `Gutenberg_Sidebar::handle_update_conversation()`

**Permission:** `check_permissions`

---

### `DELETE /conversations/(?P<session_id>[a-zA-Z0-9]+)`

Delete a conversation.

**Handler:** `Gutenberg_Sidebar::handle_delete_conversation()`

**Permission:** `check_permissions`

---

### `POST|PUT /conversations/(?P<session_id>[a-zA-Z0-9]+)/messages`

Add or update messages in a conversation.

**Handler:** `Gutenberg_Sidebar::handle_update_conversation_messages()`

**Permission:** `check_permissions`

---

### `POST /conversations/(?P<session_id>[a-zA-Z0-9]+)/link-post`

Link a conversation to a post.

**Handler:** `Gutenberg_Sidebar::handle_link_conversation_to_post()`

**Permission:** `check_permissions`

---

### `POST /conversations/(?P<session_id>[a-zA-Z0-9]+)/lock`

Acquire or refresh session lock (heartbeat).

**Handler:** `Controller_Session::handle_session_lock()`

**Permission:** `check_permissions` + conversation access

**Request Body:**
```json
{
  "tab_id": "uuid",
  "force": false
}
```

**Response:**
```json
{
  "acquired": true,
  "expires_at": 1234567890,
  "tab_id": "uuid"
}
```

---

### `DELETE /conversations/(?P<session_id>[a-zA-Z0-9]+)/lock`

Release session lock.

**Handler:** `Controller_Session::handle_session_unlock()`

**Permission:** `check_permissions` + conversation access

---

## Planning & Writing

### `GET|POST /post-config/(?P<post_id>\d+)`

Get or save post configuration (focus keyword, language, article type).

**Handler:** `Gutenberg_Sidebar::handle_get_post_config()` / `handle_save_post_config()`

**Permission:** `check_permissions` + post edit

---

### `POST /generate-plan`

Generate article outline/plan.

**Handler:** `Gutenberg_Sidebar::handle_generate_plan()`

**Permission:** `check_permissions` + post edit

---

### `POST /revise-plan`

Revise an existing plan.

**Handler:** `Gutenberg_Sidebar::handle_revise_plan()`

**Permission:** `check_permissions` + post edit

---

### `POST /execute-article`

Execute article generation from plan.

**Handler:** `Gutenberg_Sidebar::handle_execute_article()`

**Permission:** `check_permissions` + post edit

---

### `POST /reformat-blocks`

Reformat blocks (e.g., convert to different structure).

**Handler:** `Gutenberg_Sidebar::handle_reformat_blocks()`

**Permission:** `check_permissions` + post edit

---

### `POST /regenerate-block`

Regenerate a single block.

**Handler:** `Gutenberg_Sidebar::handle_regenerate_block()`

**Permission:** `check_permissions` + post edit

---

### `POST /refine-block`

Refine a block with instructions.

**Handler:** `Gutenberg_Sidebar::handle_block_refine()`

**Permission:** `check_permissions` + post edit

---

### `POST /refine-from-chat`

Refine blocks based on chat conversation.

**Handler:** `Gutenberg_Sidebar::handle_refine_from_chat()`

**Permission:** `check_permissions` + post edit

---

### `POST /refine-multi-pass`

Multi-pass block refinement.

**Handler:** `Gutenberg_Sidebar::handle_refine_multi_pass()`

**Permission:** `check_permissions` + post edit

---

### `POST /refine-article`

Article-wide refinement.

**Handler:** `Gutenberg_Sidebar::handle_refine_article()`

**Permission:** `check_permissions` + post edit

---

### `POST /summarize-context`

Summarize context to stay within token limits.

**Handler:** `Gutenberg_Sidebar::handle_summarize_context()`

**Permission:** `check_permissions` + post edit

---

## Content Quality

### `POST /check-clarity`

Check content clarity.

**Handler:** `Gutenberg_Sidebar::handle_check_clarity()`

**Permission:** `check_permissions` + post edit

---

### `POST /detect-intent`

Detect user intent from message.

**Handler:** `Gutenberg_Sidebar::handle_detect_intent()`

**Permission:** `check_permissions`

---

### `POST /suggest-improvements`

Proactive improvement suggestions (idle analysis).

**Handler:** `Gutenberg_Sidebar::handle_suggest_improvements()`

**Permission:** `check_permissions` + post edit

---

## SEO

### `GET /seo-audit/(?P<post_id>\d+)`

Run SEO audit for a post.

**Handler:** `Gutenberg_Sidebar::handle_seo_audit()`

**Permission:** `check_permissions` + post edit

---

### `POST /generate-meta`

Generate meta description.

**Handler:** `Gutenberg_Sidebar::handle_generate_meta()`

**Permission:** `check_permissions` + post edit

---

### `POST /suggest-keywords`

Suggest keywords for a post.

**Handler:** `Gutenberg_Sidebar::handle_suggest_keywords()`

**Permission:** `check_permissions` + post edit

---

### `GET /geo-score/(?P<post_id>\d+)`

Get GEO scoring for a post.

**Handler:** `Gutenberg_Sidebar::handle_geo_score()`

**Permission:** `check_permissions` + post edit

---

## Title & Excerpt

### `POST /generate-title`

Generate post title (uses WP 7.0 AI Client when available).

**Handler:** `Gutenberg_Sidebar::handle_generate_title()`

**Permission:** `check_permissions` + post edit

---

### `POST /refine-title`

Refine title with instructions.

**Handler:** `Gutenberg_Sidebar::handle_refine_title()`

**Permission:** `check_permissions` + post edit

---

### `POST /generate-excerpt`

Generate post excerpt (uses WP 7.0 AI Client when available).

**Handler:** `Gutenberg_Sidebar::handle_generate_excerpt()`

**Permission:** `check_permissions` + post edit

---

## Images

### `GET /image-recommendations/(?P<post_id>\d+)`

Get image recommendations for a post.

**Handler:** `Gutenberg_Sidebar::handle_get_image_recommendations()`

**Permission:** `check_permissions` + post edit

---

### `POST /generate-image`

Generate an image.

**Handler:** `Gutenberg_Sidebar::handle_generate_image()`

**Permission:** `check_permissions` + post edit

---

### `POST /commit-image`

Commit/save generated image.

**Handler:** `Gutenberg_Sidebar::handle_commit_image()`

**Permission:** `check_permissions` + post edit

---

## Writing State

### `GET /writing-state/(?P<post_id>\d+)`

Get writing state for a post.

**Handler:** `Gutenberg_Sidebar::handle_get_writing_state()`

**Permission:** `check_permissions` + post edit

---

### `POST /writing-state/(?P<post_id>\d+)`

Save writing state.

**Handler:** `Gutenberg_Sidebar::handle_save_writing_state()`

**Permission:** `check_permissions` + post edit

---

## Section Blocks

### `POST /section-blocks`

Save section block mapping.

**Handler:** `Gutenberg_Sidebar::handle_save_section_blocks()`

**Permission:** `check_permissions`

---

### `GET /section-blocks/(?P<post_id>\d+)`

Get section blocks for a post.

**Handler:** `Gutenberg_Sidebar::handle_get_section_blocks()`

**Permission:** `check_permissions` + post edit

---

## Cost Tracking

### `GET /cost-tracking/(?P<post_id>\d+)`

Get cost tracking data.

**Handler:** `Controller_Cost::handle_get_cost_tracking()`

**Permission:** `check_permissions` + post edit (if `post_id` > 0)

---

## AI Capabilities

### `GET /ai-capabilities`

Get AI capabilities status.

**Handler:** `Gutenberg_Sidebar::handle_get_ai_capabilities()`

**Permission:** `check_permissions`

---

## Research

### `POST /search`

Search the web (Brave Search).

**Handler:** `Controller_Chat::handle_search()`

**Permission:** `check_permissions`

**Rate Limit:** 20 requests/minute

---

### `POST /fetch-content`

Fetch web page content.

**Handler:** `Controller_Chat::handle_fetch_content()`

**Permission:** `check_permissions`

**Rate Limit:** 10 requests/minute

---

### `POST /research-summary`

Generate research summary.

**Handler:** `Controller_Chat::handle_research_summary()`

**Permission:** `check_permissions`

---

## MEMANTO (Memory)

### `GET /memanto/status`

Get MEMANTO service status.

**Handler:** `Gutenberg_Sidebar::handle_memanto_status()`

**Permission:** `check_permissions`

---

### `GET /memanto/recall`

Recall recent memories for a post.

**Handler:** `Gutenberg_Sidebar::handle_memanto_recall()`

**Permission:** `check_permissions`

---

### `GET /memanto/restore`

Restore session for cross-session continuity.

**Handler:** `Gutenberg_Sidebar::handle_memanto_restore()`

**Permission:** `check_permissions`

---

### `GET /memanto/preferences`

Get user preferences for new post carry-over.

**Handler:** `Gutenberg_Sidebar::handle_memanto_preferences()`

**Permission:** `check_permissions`

---

## User Preferences

### `GET /user-preferences`

Get user preferences (public — no auth required).

**Handler:** `Gutenberg_Sidebar::handle_get_user_preferences()`

**Permission:** `__return_true` (public)

---

### `POST /user-preferences`

Save user preferences.

**Handler:** `Gutenberg_Sidebar::handle_save_user_preferences()`

**Permission:** `check_permissions`

---

## Migration

### `POST /migrate-chat-history/(?P<post_id>\d+)`

Migrate legacy post meta chat history to conversations table.

**Handler:** `Gutenberg_Sidebar::handle_migrate_chat_history()`

**Permission:** `check_permissions` + post edit

---

## Error Codes

| Code | HTTP Status | Description |
|------|-------------|-------------|
| `forbidden` | 403 | User lacks permission for this action |
| `invalid_post` | 400 | Invalid or missing post ID |
| `rate_limit_exceeded` | 429 | Too many requests |
| `missing_tab_id` | 400 | Session lock requires tab_id |
| Various WP_Error codes | varies | Provider-specific errors |

---

## Response Format

All responses are JSON. Successful responses:

```json
{
  "status": "success",
  "data": { ... }
}
```

Or directly the resource data:

```json
{
  "key": "value"
}
```

Error responses:

```json
{
  "code": "error_code",
  "message": "Human-readable message",
  "data": { "status": 400 }
}
```