Files

6.3 KiB

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=<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=<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=<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=<token>

Delete Session

DELETE /api/sessions/{sessionId}
Cookie: __Secure-better-auth.session_token=<token>

Change Model

POST /api/sessions/{sessionId}/model
Content-Type: application/json
Cookie: __Secure-better-auth.session_token=<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=<token>

Response: {"older": [...], "newStageBase": N, "newLogBase": N, "hasOlder": true/false}

Management Endpoints

Active Sessions

GET /api/sessions/active
Cookie: __Secure-better-auth.session_token=<token>

Pinned Sessions

GET /api/sessions/pinned
Cookie: __Secure-better-auth.session_token=<token>

Session History

GET /api/sessions/history?limit=50                     // first page
GET /api/sessions/history?limit=50&cursor=<encoded>    // next page
Cookie: __Secure-better-auth.session_token=<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=<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=<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):

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