HTTP API
Table of contents
- Enabling the HTTP Server
- Endpoints Overview
- Endpoint Details
- POST
/ - GET
/sessions - GET
/sessions/{id} - GET
/sessions/{id}/raw - GET
/providers - GET
/messages - POST
/session/new - DELETE
/session/{id} - POST
/session/{id}/stop - POST
/session/{id}/clear - POST
/session/{id}/retry - PUT
/session/{id}/provider - PUT
/session/{id}/model - PUT
/session/{id}/cwd - PUT
/session/{id}/pin - PUT
/session/{id}/title - GET
/session
- POST
- Message Queue System
- Common Response Status Codes
- Usage Examples
- Security Considerations
- Integration Ideas
- Next Steps
chat.nvim includes a built-in HTTP server built on libuv TCP, allowing external applications to interact with chat sessions. This enables integration with CLI tools, CI/CD pipelines, web applications, and more.
Enabling the HTTP Server
The HTTP server is automatically started when http.api_key is set to a non-empty value:
require('chat').setup({
-- ... other configuration
http = {
host = '127.0.0.1', -- Default: '127.0.0.1'
port = 7777, -- Default: 7777
api_key = 'your-secret-key', -- Required to enable server
},
})
Base URL: http://{host}:{port}
Authentication: All requests except GET /session (HTML preview) require the X-API-Key header.
Endpoints Overview
| Endpoint | Method | Description |
|---|---|---|
/ |
POST | Push a message to a session’s message queue |
/sessions |
GET | List all sessions with details |
/sessions/{id} |
GET | Get a single session’s details |
/sessions/{id}/raw |
GET | Get a session’s raw cache JSON |
/providers |
GET | List all available providers and their models |
/messages |
GET | Get messages for a session |
/session/new |
POST | Create a new session |
/session/{id} |
DELETE | Delete a session |
/session/{id}/stop |
POST | Stop generation |
/session/{id}/clear |
POST | Clear all messages in a session |
/session/{id}/retry |
POST | Retry the last message |
/session/{id}/provider |
PUT | Set the provider for a session |
/session/{id}/model |
PUT | Set the model for a session |
/session/{id}/cwd |
PUT | Set the working directory for a session |
/session/{id}/pin |
PUT | Set the pin status for a session |
/session/{id}/title |
PUT | Set the title for a session |
/session |
GET | Get HTML preview of a session (no auth required) |
Endpoint Details
POST /
Push a message to a session’s message queue. The message will be delivered once the session is idle.
Request Body:
{
"session": "2024-01-15-10-30-00",
"content": "Hello from external app!"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
session |
string | Yes | Target session ID |
content |
string | Yes | Message content |
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — message queued |
| 400 | Invalid JSON body or missing required fields |
| 401 | Invalid or missing API key |
Example:
curl -X POST http://127.0.0.1:7777/ \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"session": "2024-01-15-10-30-00", "content": "What is the weather today?"}'
GET /sessions
Get a list of all sessions with details.
Response (200 OK):
[
{
"id": "2024-01-15-10-30-00",
"title": "Help me write a Lua plugin...",
"cwd": "/home/user/project",
"provider": "openai",
"model": "gpt-4o",
"pin": false,
"in_progress": false,
"message_count": 5,
"last_message": {
"role": "assistant",
"content": "I'd be happy to help you write a Lua plugin for Neovim. Let's start by...",
"created": 1705315800
}
}
]
Response Fields:
| Field | Type | Description |
|---|---|---|
id |
string | Session ID (format: YYYY-MM-DD-HH-MM-SS) |
title |
string | Session title (auto-extracted from first user message, max 50 chars) |
cwd |
string | Session working directory |
provider |
string | Provider name |
model |
string | Model name |
pin |
boolean | Whether the session is pinned |
in_progress |
boolean | Whether generation is in progress |
message_count |
number | Total number of messages |
last_message |
object|null | Last message object (null if no messages) |
last_message Object:
| Field | Type | Description |
|---|---|---|
role |
string | Message role (user / assistant) |
content |
string | Message content (truncated to 100 chars) |
created |
number | Unix timestamp of message creation |
Example:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/sessions
GET /sessions/{id}
Get details for a single session.
Path Parameters:
| Parameter | Description |
|---|---|
id |
Session ID |
Response (200 OK):
Same format as a single element in the GET /sessions response.
Response Status Codes:
| Status Code | Description |
|---|---|
| 200 | Success |
| 404 | Session not found |
Example:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/sessions/2024-01-15-10-30-00
GET /sessions/{id}/raw
Get the raw cache JSON content for a session. Includes all messages, metadata, usage statistics, and complete session state.
Path Parameters:
| Parameter | Description |
|---|---|
id |
Session ID |
Response Status Codes:
| Status Code | Description |
|---|---|
| 200 | Success — returns raw JSON content |
| 404 | Cache file not found |
| 500 | Failed to read cache file |
Example:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/sessions/2024-01-15-10-30-00/raw
GET /providers
Get all registered providers and their available models.
Response (200 OK):
[
{
"name": "anthropic",
"models": ["claude-3-5-sonnet-20241022", "claude-3-opus-20240229"]
},
{
"name": "deepseek",
"models": ["deepseek-chat", "deepseek-coder"]
},
{
"name": "openai",
"models": ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo"]
}
]
Response Fields:
| Field | Type | Description |
|---|---|---|
name |
string | Provider name (e.g., openai, anthropic) |
models |
string[] | List of available models (from available_models()) |
Example:
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/providers
GET /messages
Get the message list for a specific session, with optional pagination.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
session |
string | Yes | Session ID |
since |
number | No | Starting index (1-indexed) |
Response (200 OK):
[
{
"role": "user",
"content": "Hello!"
},
{
"role": "assistant",
"content": "Hi there! How can I help you?",
"reasoning_content": "The user is greeting me...",
"tool_calls": null,
"tool_call_id": null,
"created": 1705315800,
"usage": {
"total_tokens": 50,
"prompt_tokens": 20,
"completion_tokens": 30
},
"error": null,
"tool_call_state": null
}
]
Message Object Fields:
| Field | Type | Description |
|---|---|---|
role |
string | Role: user / assistant / tool / system |
content |
string|null | Message content (may be null for tool calls) |
reasoning_content |
string|null | Reasoning content (for thinking models) |
tool_calls |
array|null | Tool calls made by assistant |
tool_call_id |
string|null | Tool call ID (for tool role messages) |
created |
number|null | Unix timestamp |
usage |
object|null | Token usage statistics (total_tokens, prompt_tokens, completion_tokens) |
error |
string|null | Error message if request failed |
tool_call_state |
string|null | Tool call execution state |
Response Status Codes:
| Status Code | Description |
|---|---|
| 200 | Success |
| 400 | Missing session parameter |
| 404 | Session not found |
Examples:
# Get all messages
curl "http://127.0.0.1:7777/messages?session=2024-01-15-10-30-00" \
-H "X-API-Key: your-secret-key"
# Get messages starting from index 5
curl "http://127.0.0.1:7777/messages?session=2024-01-15-10-30-00&since=5" \
-H "X-API-Key: your-secret-key"
POST /session/new
Create a new session, optionally specifying the provider and model.
Request Body (optional):
{
"provider": "openai",
"model": "gpt-4o"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
provider |
string | No | Provider to use |
model |
string | No | Model to use |
Response (200 OK):
{
"id": "2024-01-15-10-30-00",
"title": "",
"cwd": "/home/user/project",
"provider": "openai",
"model": "gpt-4o",
"in_progress": false,
"message_count": 0,
"last_message": null
}
Response Fields:
| Field | Type | Description |
|---|---|---|
id |
string | Newly created session ID |
title |
string | Session title (empty for new sessions) |
cwd |
string | Current working directory |
provider |
string | Provider name |
model |
string | Model name |
in_progress |
boolean | Generation status (false for new sessions) |
message_count |
number | Message count (0 for new sessions) |
last_message |
null | Last message (null for new sessions) |
Examples:
# Create session with default provider/model
curl -X POST http://127.0.0.1:7777/session/new \
-H "X-API-Key: your-secret-key"
# Create session with custom provider/model
curl -X POST http://127.0.0.1:7777/session/new \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"provider": "openai", "model": "gpt-4o"}'
DELETE /session/{id}
Delete a session.
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — session deleted |
| 404 | Session not found |
| 409 | Session is in progress, cannot delete |
Example:
curl -X DELETE http://127.0.0.1:7777/session/2024-01-15-10-30-00 \
-H "X-API-Key: your-secret-key"
POST /session/{id}/stop
Stop generation for a session.
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — generation stopped |
| 404 | Session not found |
Example:
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/stop \
-H "X-API-Key: your-secret-key"
POST /session/{id}/clear
Clear all messages and usage statistics for a session. The session itself is preserved.
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — session cleared |
| 404 | Session not found |
| 409 | Session is in progress, cannot clear |
| 500 | Failed to clear session |
Example:
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/clear \
-H "X-API-Key: your-secret-key"
POST /session/{id}/retry
Retry the last user message. Re-sends the last user message to the AI provider.
Note: Only works if the last message is not from the
assistantrole.
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — retry initiated |
| 404 | Session not found |
| 409 | Session is in progress, cannot retry |
| 400 | No message to retry (no messages or last is already assistant) |
Example:
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/retry \
-H "X-API-Key: your-secret-key"
PUT /session/{id}/provider
Set the provider for a session.
Request Body:
{
"provider": "anthropic"
}
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — provider updated |
| 404 | Session not found |
| 400 | Missing or invalid provider value |
Example:
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/provider \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"provider": "anthropic"}'
PUT /session/{id}/model
Set the model for a session.
Request Body:
{
"model": "claude-3-5-sonnet-20241022"
}
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — model updated |
| 404 | Session not found |
| 400 | Missing or invalid model value |
Example:
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/model \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"model": "claude-3-5-sonnet-20241022"}'
PUT /session/{id}/cwd
Set the working directory for a session.
Request Body:
{
"cwd": "/path/to/project"
}
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — working directory updated |
| 404 | Session not found |
| 400 | Missing or invalid cwd value |
Example:
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/cwd \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"cwd": "/home/user/new-project"}'
PUT /session/{id}/pin
Set the pin status for a session.
Request Body:
{
"pin": true
}
Parameters:
| Parameter | Type | Description |
|---|---|---|
pin |
boolean | Pin status (true = pinned, false = unpinned) |
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — pin status updated |
| 404 | Session not found |
| 400 | Missing or invalid pin value |
Examples:
# Pin a session
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/pin \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"pin": true}'
# Unpin a session
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/pin \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"pin": false}'
PUT /session/{id}/title
Set a custom title for a session.
Request Body:
{
"title": "My custom title"
}
Response Status Codes:
| Status Code | Description |
|---|---|
| 204 | Success — title updated |
| 404 | Session not found |
| 400 | Missing or invalid title value |
Example:
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/title \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"title": "Debugging Lua plugin"}'
GET /session
Get an HTML preview of a session (no authentication required, accessible directly from a browser).
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Session ID |
Response Status Codes:
| Status Code | Description |
|---|---|
| 200 | Success — returns HTML content |
| 400 | Missing id parameter |
| 404 | Session not found |
Examples:
# Command line
curl "http://127.0.0.1:7777/session?id=2024-01-15-10-30-00"
# Browser
# http://127.0.0.1:7777/session?id=2024-01-15-10-30-00
Message Queue System
Messages pushed via POST / enter an internal queue, processed by a timer-based poller to ensure reliable, ordered delivery.
External App → POST / → Message Queue → Timer (5s) → Deliver to Session
How it works:
- Messages are immediately queued upon receipt
- A timer checks the queue every 5 seconds
- When a session is idle (
in_progressis false), messages are delivered in FIFO order - If a session is busy, messages remain in the queue until it becomes available
This ensures messages are never lost and are delivered in the order they were sent.
Common Response Status Codes
These status codes apply across all endpoints:
| Status Code | Description |
|---|---|
| 200 | Success — returns JSON data |
| 204 | Success — no content returned |
| 400 | Bad request (JSON parse error, missing parameters, etc.) |
| 401 | Invalid or missing API key |
| 404 | Resource not found or wrong method/path |
Usage Examples
curl
# Send message
curl -X POST http://127.0.0.1:7777/ \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"session": "2024-01-15-10-30-00", "content": "Hello from curl!"}'
# List sessions
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/sessions
# List providers
curl -H "X-API-Key: your-secret-key" http://127.0.0.1:7777/providers
# Create new session
curl -X POST http://127.0.0.1:7777/session/new \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"provider": "openai", "model": "gpt-4o"}'
# Set provider
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/provider \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"provider": "anthropic"}'
# Set model
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/model \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"model": "claude-3-5-sonnet-20241022"}'
# Set working directory
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/cwd \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"cwd": "/home/user/project"}'
# Pin session
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/pin \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"pin": true}'
# Set title
curl -X PUT http://127.0.0.1:7777/session/2024-01-15-10-30-00/title \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d '{"title": "My custom title"}'
# Delete session
curl -X DELETE http://127.0.0.1:7777/session/2024-01-15-10-30-00 \
-H "X-API-Key: your-secret-key"
# Stop generation
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/stop \
-H "X-API-Key: your-secret-key"
# Clear messages
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/clear \
-H "X-API-Key: your-secret-key"
# Retry last message
curl -X POST http://127.0.0.1:7777/session/2024-01-15-10-30-00/retry \
-H "X-API-Key: your-secret-key"
# Get messages (with pagination)
curl "http://127.0.0.1:7777/messages?session=2024-01-15-10-30-00&since=5" \
-H "X-API-Key: your-secret-key"
# Get raw cache
curl "http://127.0.0.1:7777/sessions/2024-01-15-10-30-00/raw" \
-H "X-API-Key: your-secret-key"
# Get HTML preview (no API key needed)
curl "http://127.0.0.1:7777/session?id=2024-01-15-10-30-00"
Python
import requests
BASE_URL = "http://127.0.0.1:7777"
HEADERS = {"X-API-Key": "your-secret-key"}
# Send a message
def send_message(session_id: str, content: str) -> bool:
resp = requests.post(
f"{BASE_URL}/",
json={"session": session_id, "content": content},
headers=HEADERS,
)
return resp.status_code == 204
# List all sessions
def list_sessions() -> list:
resp = requests.get(f"{BASE_URL}/sessions", headers=HEADERS)
return resp.json() if resp.status_code == 200 else []
# List all providers
def list_providers() -> list:
resp = requests.get(f"{BASE_URL}/providers", headers=HEADERS)
return resp.json() if resp.status_code == 200 else []
# Create a new session
def create_session(provider: str = None, model: str = None) -> str:
body = {}
if provider:
body["provider"] = provider
if model:
body["model"] = model
resp = requests.post(
f"{BASE_URL}/session/new",
json=body if body else None,
headers=HEADERS,
)
return resp.json().get("id") if resp.status_code == 200 else None
# Get messages
def get_messages(session_id: str, since: int = None) -> list:
params = {"session": session_id}
if since:
params["since"] = since
resp = requests.get(f"{BASE_URL}/messages", params=params, headers=HEADERS)
return resp.json() if resp.status_code == 200 else []
# Delete a session
def delete_session(session_id: str) -> bool:
resp = requests.delete(f"{BASE_URL}/session/{session_id}", headers=HEADERS)
return resp.status_code == 204
# Usage example
if __name__ == "__main__":
# Create a new session
session_id = create_session(provider="openai", model="gpt-4o")
if session_id:
print(f"Created session: {session_id}")
# Send a message
send_message(session_id, "Hello from Python!")
# List all sessions
for s in list_sessions():
print(f"Session: {s['id']}, Provider: {s['provider']}, Messages: {s['message_count']}")
JavaScript / Node.js
const BASE_URL = "http://127.0.0.1:7777";
const HEADERS = { "X-API-Key": "your-secret-key" };
// Send a message
async function sendMessage(sessionId, content) {
const resp = await fetch(`${BASE_URL}/`, {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: JSON.stringify({ session: sessionId, content }),
});
return resp.status === 204;
}
// List sessions
async function listSessions() {
const resp = await fetch(`${BASE_URL}/sessions`, { headers: HEADERS });
return resp.ok ? resp.json() : [];
}
// List providers
async function listProviders() {
const resp = await fetch(`${BASE_URL}/providers`, { headers: HEADERS });
return resp.ok ? resp.json() : [];
}
// Create a new session
async function createSession(provider, model) {
const body = {};
if (provider) body.provider = provider;
if (model) body.model = model;
const resp = await fetch(`${BASE_URL}/session/new`, {
method: "POST",
headers: { ...HEADERS, "Content-Type": "application/json" },
body: Object.keys(body).length ? JSON.stringify(body) : undefined,
});
return resp.ok ? (await resp.json()).id : null;
}
// Get messages
async function getMessages(sessionId, since) {
const params = new URLSearchParams({ session: sessionId });
if (since) params.set("since", since);
const resp = await fetch(`${BASE_URL}/messages?${params}`, { headers: HEADERS });
return resp.ok ? resp.json() : [];
}
// Usage example
(async () => {
const sessionId = await createSession("openai", "gpt-4o");
if (sessionId) {
console.log(`Created session: ${sessionId}`);
await sendMessage(sessionId, "Hello from Node.js!");
const sessions = await listSessions();
sessions.forEach((s) =>
console.log(`Session: ${s.id}, Provider: ${s.provider}, Messages: ${s.message_count}`)
);
}
})();
Security Considerations
⚠️ Important Security Notes
- API Key Protection: Use a strong key (generate with
openssl rand -hex 32). Never commit it to version control - Network Isolation: The server binds to
127.0.0.1by default (local only). If exposing externally, use an HTTPS reverse proxy - Input Validation: All request bodies are validated for proper JSON format and field types
- Rate Limiting: Implement external rate limiting if needed for your use case
Integration Ideas
CI/CD Pipelines
# Send build notifications to a chat session
curl -X POST http://127.0.0.1:7777/ \
-H "X-API-Key: your-secret-key" \
-H "Content-Type: application/json" \
-d "{\"session\": \"$SESSION_ID\", \"content\": \"Build #$BUILD_NUMBER completed: $STATUS\"}"
Monitoring Dashboard
// Display providers and models in a web dashboard
async function updateDashboard() {
const resp = await fetch("http://127.0.0.1:7777/providers", {
headers: { "X-API-Key": "your-secret-key" },
});
const providers = await resp.json();
document.getElementById("provider-list").innerHTML = providers
.map((p) => `<li>${p.name} — ${p.models.length} models</li>`)
.join("");
}
Next Steps
- Providers — AI provider configuration
- Tools — Tool system
- Memory System — Memory system configuration
- IM Integration — Instant messaging integrations