# conol.ai Chat API Endpoints (2026-07-23) Discovered from JS bundle analysis of `/_next/static/immutable/chunks/` on conol.ai. ## Architecture - **Frontend**: Next.js SPA with Turbopack - **Auth**: `better-auth` (session token in `__Secure-better-auth.session_token` cookie) - **Chat**: SSE (Server-Sent Events) via `EventSource` - **Subdomain**: `agent.conol.ai` for health checks only (`/api/health` → `{"ok":true}`) ## Authentication The session token is stored in cookie `__Secure-better-auth.session_token` (URL-encoded value). All API calls require this cookie. Bearer token in `Authorization` header returns `Invalid API key`. Other cookies in the session: - `__Secure-better-auth.better-auth-passkey` — passkey auth - `user_session`, `__Host-user_session_same_site` — GitHub session - `logged_in`, `dotcom_user` — GitHub login state ## Chat Endpoints ### Create Session ``` POST /api/sessions Content-Type: application/json Cookie: __Secure-better-auth.session_token= { "source": "web", "messages": [ {"type": "text", "content": "Hello"}, {"type": "image", "url": "https://..."} // optional ], "timezone": "Europe/Moscow", "agentServerId": "optional-server-id", "agentName": "optional-agent-name", "agentModel": "optional-model-id", "modelPreset": "optional-preset", "agentEffort": "optional-effort" } Response: {"sessionId": "..."} ``` ### Send Message to Existing Session ``` POST /api/sessions/{sessionId}/messages Content-Type: application/json Cookie: __Secure-better-auth.session_token= { "messages": [{"type": "text", "content": "Hello"}], "timezone": "Europe/Moscow" } Response: 200 OK ``` ### Stream Messages (SSE) ``` GET /api/sessions/{sessionId}/messages?logDeltas=1 Cookie: __Secure-better-auth.session_token= // SSE events: event: history → {"messages": [...], "todoList": [...], "statusMessage": "...", "intention": "...", "title": "...", "sandboxAccess": [...], "sandboxStatus": "ready"} event: history_delta → {"stages": [...], "windowReset": true/false, "from": N, "logFrom": N, "intention": "...", "agentSessionId": "...", "title": "...", "todoList": [...], "contextUsage": {...}, "pendingQuestionary": {...}, "sandboxAccess": [...]} event: assistant → {"message": {"content": [...]}} event: stream_event → {"delta": {"type": "text_delta", "text": "..."}} event: thinking → {"message": {"content": "..."}} event: tool_use → {"tool": "...", "brief": "..."} event: plan → {"todoList": [...], "totalTodos": N, "doneTodos": N} event: status → {"message": {"content": "..."}} event: intention → {"message": {"content": "..."}} event: questionary → {...} event: sandbox_ready → {"sandboxAccess": [...]} event: sandbox_paused → (no payload) event: sandbox_resuming → (no payload) event: done → (no payload) event: error → {"message": {"content": "..."}} event: result → {"message": {"subtype": "success|error", "content": "..."}} event: insufficient_balance → (no payload) ``` ### Stop Generation ``` PUT /api/sessions/{sessionId}/stop Cookie: __Secure-better-auth.session_token= ``` ### Delete Session ``` DELETE /api/sessions/{sessionId} Cookie: __Secure-better-auth.session_token= ``` ### Change Model ``` POST /api/sessions/{sessionId}/model Content-Type: application/json Cookie: __Secure-better-auth.session_token= { "agentModel": "model-id", "modelPreset": "preset", "agentEffort": "effort" } ``` ### Load Older Messages ``` GET /api/sessions/{sessionId}/stages?beforeStage=N&beforeLog=N Cookie: __Secure-better-auth.session_token= Response: {"older": [...], "newStageBase": N, "newLogBase": N, "hasOlder": true/false} ``` ## Management Endpoints ### Active Sessions ``` GET /api/sessions/active Cookie: __Secure-better-auth.session_token= ``` ### Pinned Sessions ``` GET /api/sessions/pinned Cookie: __Secure-better-auth.session_token= ``` ### Session History ``` GET /api/sessions/history?limit=50 // first page GET /api/sessions/history?limit=50&cursor= // next page Cookie: __Secure-better-auth.session_token= ``` ## Other Endpoints ### Agent Servers (Model List) ``` GET /api/agent-servers // Returns 28+ models: claude-opus-4-8, gpt-5.6-sol, deepseek-v4-pro, grok-4.3, etc. // No auth required for this endpoint ``` ### Billing ``` GET /api/billing/balance GET /api/billing/subscription GET /api/billing/catalog Cookie: __Secure-better-auth.session_token= ``` ### Auth ``` POST /api/auth/sign-in/email → CAPTCHA_MISSING (Cloudflare Turnstile) POST /api/auth/sign-in/social → 429 rate limited POST /api/auth/sign-up → 404 ``` ### Secrets (API Keys) ``` GET /api/secrets POST /api/secrets → {"name": "...", "domains": [...], "value": "sk-..."} DELETE /api/secrets/{id} Cookie: __Secure-better-auth.session_token= ``` ## OmniRoute Provider Pattern For building a proxy handler, follow the OmniRoute web-cookie provider pattern: **Registry Entry** (in `open-sse/config/providers/registry/conol-web/index.ts`): ```typescript export const conol_webProvider: RegistryEntry = { id: "conol-web", alias: "cw", format: "openai", executor: "conol-web", baseUrl: "https://conol.ai", authType: "apikey", authHeader: "cookie", models: [ { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", toolCalling: true }, { id: "claude-opus-4-8", name: "Claude Opus 4.8", toolCalling: true }, // ... all 28+ models from /api/agent-servers ], }; ``` **Executor** (in `open-sse/executors/conol-web.ts`): 1. Accept cookie as `apiKey` (the session token) 2. POST `/api/sessions` to create a chat session 3. Connect to SSE stream at `/api/sessions/{id}/messages?logDeltas=1` 4. Parse `stream_event` deltas → OpenAI-compatible streaming chunks 5. Handle `done` event → close stream 6. On error → translate to OpenAI error format ## Blockers - **Rate limiting**: `/api/auth/sign-in/social` returns 429 after ~3 attempts - **CAPTCHA**: `/api/auth/sign-in/email` requires Cloudflare Turnstile - **Anti-bot**: Browserbase headless browsers blocked on OAuth flow - **Session expiry**: Session tokens from banned accounts return 401 - **No public API**: conol.ai has no OpenAI-compatible REST endpoint — only internal SSE API