HTTP API

Table of contents


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 assistant role.

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:

  1. Messages are immediately queued upon receipt
  2. A timer checks the queue every 5 seconds
  3. When a session is idle (in_progress is false), messages are delivered in FIFO order
  4. 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

  1. API Key Protection: Use a strong key (generate with openssl rand -hex 32). Never commit it to version control
  2. Network Isolation: The server binds to 127.0.0.1 by default (local only). If exposing externally, use an HTTPS reverse proxy
  3. Input Validation: All request bodies are validated for proper JSON format and field types
  4. 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