API Reference
ChatSorter exposes a simple REST API for storing, searching, and retrieving
memories from your AI application. All requests and responses use JSON.
The hosted API runs at api.chatsorter.com; the self-hosted tier
runs the same interface on your own machine.
Overview
The ChatSorter API is a memory layer for LLM applications. It takes incoming chat messages, extracts what matters (entities, decisions, emotions), embeds them into a vector store, and makes them retrievable by semantic search — so your AI always has relevant context at hand without blowing up your token budget.
Three concepts to know:
| Concept | What it is |
|---|---|
| chat_id | A string that groups messages into one conversation. Use any slug you want — user IDs, session IDs, or random strings all work. |
| Memory | An extracted fact or event stored with an importance score and timestamp. Memories decay over time unless reinforced. |
| Retrieval | A semantic search over a chat's memories ranked by relevance, importance, and recency. |
Authentication
Every request must include your API key in the X-API-Key header.
You can find your key on the dashboard after signing up.
X-API-Key: cs_live_xxxxxxxxxxxxxxxxxxxxxxxx
Base URL
All hosted API endpoints are rooted at:
https://api.chatsorter.com
Self-hosted instances default to http://localhost:5000.
The port is configurable in chatsorter.json.
Errors
The API returns standard HTTP status codes. Error responses include a
JSON body with a error field describing what went wrong.
| Status | Meaning |
|---|---|
| 400 | Bad request — a required field is missing or a value is out of range. |
| 401 | Unauthorized — API key is missing or invalid. |
| 429 | Rate limit exceeded — slow down requests or upgrade your plan. |
| 500 | Internal server error — something went wrong on our end. |
// Example error response
{
"error": "Invalid API key.",
"status": 401
}
Process a message
Ingests a single chat message, extracts memories (entities, decisions, emotional signals), and stores them in the vector DB for later retrieval. Call this after every AI or user message in your conversation loop.
Request body
| Field | Type | Description |
|---|---|---|
| chat_id required | string | Unique identifier for the conversation. Alphanumeric, underscores, and hyphens only (1–100 chars). |
| message required | string | The message text to process. Max 50,000 characters. |
| role optional | string | "user" or "assistant". Defaults to "user". |
| importance_override optional | number | Manually set an importance score (0–10) instead of auto-detecting it. |
Example request
fetch("https://api.chatsorter.com/process", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "cs_live_xxxx"
},
body: JSON.stringify({
chat_id: "user_42",
message: "I decided to go with the RTX 4070 over the 4080.",
role: "user"
})
})
Response
{
"success": true,
"memories_stored": 2,
"entities": [
{ "type": "gpu", "value": "RTX 4070" },
{ "type": "gpu", "value": "RTX 4080" }
],
"decisions": [
{ "text": "go with the RTX 4070 over the 4080", "sentiment": "positive" }
],
"importance": 7.4
}
Search memories
Retrieves memories for a conversation ranked by a blend of semantic similarity, importance score, and recency. Call this before each LLM request to inject relevant context into your prompt.
Request body
| Field | Type | Description |
|---|---|---|
| chat_id required | string | The conversation to search memories for. |
| query required | string | Natural language query describing what context you need. Max 1,000 characters. |
| max_memories optional | integer | Maximum number of memories to return. Default 10, max 100. |
| importance_threshold optional | number | Only return memories above this importance score (0–10). Default 0. |
Example request
fetch("https://api.chatsorter.com/search", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "cs_live_xxxx"
},
body: JSON.stringify({
chat_id: "user_42",
query: "what GPU did the user decide on?",
max_memories: 5
})
})
Response
{
"memories": [
{
"id": "mem_8f2a...",
"text": "User decided to go with the RTX 4070 over the 4080.",
"importance": 7.4,
"score": 0.91,
"created_at": "2026-10-13T14:22:00Z"
}
],
"count": 1
}
## Relevant context section.
Limit to 5–8 memories to stay within typical context windows.
Process and search (combined)
A convenience endpoint that does both in one call: stores the incoming message and returns the top memories relevant to it. Useful when your loop is process-then-retrieve in the same step.
Request body
| Field | Type | Description |
|---|---|---|
| chat_id required | string | Conversation identifier. |
| message required | string | Incoming message to process and use as the search query. |
| role optional | string | "user" or "assistant". Defaults to "user". |
| max_memories optional | integer | Memories to return. Default 10. |
Response
{
"processed": {
"memories_stored": 2,
"importance": 7.4
},
"memories": [
{
"id": "mem_8f2a...",
"text": "User decided to go with the RTX 4070.",
"importance": 7.4,
"score": 0.91,
"created_at": "2026-10-13T14:22:00Z"
}
]
}
Health check
Returns the server status and current time. No authentication required. Useful for uptime monitoring.
{
"status": "ok",
"time": "2026-10-13T14:22:00Z",
"version": "1.0.0"
}
Quickstart
A complete Python example — connect ChatSorter to any LLM chat loop in under 20 lines.
import requests
BASE = "https://api.chatsorter.com"
KEY = "cs_live_xxxx"
HDRS = {"X-API-Key": KEY, "Content-Type": "application/json"}
CHAT = "user_42"
def chat(user_msg):
# 1. store + retrieve in one call
r = requests.post(f"{BASE}/chat", json={
"chat_id": CHAT,
"message": user_msg,
"max_memories": 5
}, headers=HDRS).json()
# 2. build context block
context = "\n".join(m["text"] for m in r["memories"])
# 3. pass to your LLM (openai, claude, etc.)
system = f"You are a helpful assistant.\n\n## Relevant context\n{context}"
return system # use this as your system prompt
print(chat("What GPU should I pair with my i7-13700K?"))
Rate limits
Limits are applied per API key, per minute.
| Plan | Requests / min | Monthly calls |
|---|---|---|
| Free beta | 60 | Unlimited (fair use) |
| Starter — $16/mo | 300 | 150,000 |
| Pro — $85/mo | 1,000 | 1,000,000 |
| Enterprise | Custom | Custom |
When you hit a limit the API returns 429 with a
Retry-After header (seconds until the window resets).
Self-Hosted (Local Tier)
The self-hosted tier runs the exact same API on your own machine — no
conversation data leaves your server. It ships as a compiled pip package (Cython-protected,
no raw source distributed) and validates a license key weekly over a brief phone-home to
api.chatsorter.com. A 7-day offline grace period means a short outage won't
take your server down.
Install
# 1. Install Ollama (https://ollama.ai) and pull the two models
ollama pull qwen2.5:3b
ollama pull nomic-embed-text
# 2. Install ChatSorter Local
pip install chatsorter-local
# 3. Run the setup wizard — prompts for your license key
chatsorter-local init
# 4. Start the server
chatsorter-local start
# 5. Confirm it's running
curl http://localhost:5000/health
Configuration
The setup wizard creates chatsorter.json in your working directory.
You can also edit it directly or use the CLI (chatsorter-local config set <key> <value>).
The full nested structure:
{
"license_key": "cs_local_YOUR_KEY_HERE",
"server": {
"port": 5000,
"api_key": "your-local-api-key"
},
"storage": { "data_dir": "./data" },
"models": {
"summarizer": "qwen2.5:3b",
"embedder": "nomic-embed-text",
"ollama_url": "http://localhost:11434"
},
"summaries": { "messages_per_summary": 5 },
"retrieval": { "max_results": 10 },
"retention": { "shred_after_days": 365 }
}
Pricing
1 month free trial, then $10/month. The API interface
is identical to hosted — switching later just means updating your
BASE_URL from https://api.chatsorter.com to http://localhost:5000.
See full pricing →