API Endpoints
OpenSync exposes a REST API through Convex HTTP endpoints. The session, sync and search endpoints use API keys;/health is public.
Base URL
For the hosted version:.convex.site) or a verified custom HTTP domain. Do not use the Convex client domain for REST requests:
Authentication
All endpoints (except/health) require an API key in the Authorization header:
osk_ and are tied to your user account.
Sync endpoints
These endpoints are used by sync plugins to push session and message data.POST /sync/session
Create or update a session. Uses upsert logic based onexternalId, so calling this multiple times with the same externalId is safe.
Request body:
Optional fields:
Response:
POST /sync/message
Create or update a message within a session. The session is identified bysessionExternalId and will be auto-created if it does not exist.
Request body:
Optional fields:
Part types:
POST /sync/batch
Sync multiple sessions and messages in a single request. Preferred for bulk operations to reduce write conflicts. Request body:errors even when the HTTP status is 200 and ok is true. The current batch validators do not accept createdAt timestamps. Timestamp compatibility is tracked in issue #29.
GET /sync/sessions/list
Returns{ "sessionIds": [...] } containing the authenticated user’s external session IDs. Plugins use this to skip already imported sessions.
Query endpoints
GET /api/sessions
Returns{ "sessions": [...] }, ordered by most recently updated. limit defaults to 50. This route currently has no cursor or source-filter parameter.
Each session includes id, externalId, token totals, cost, visibility, message count and timestamps. Title, model, provider and project fields are present when recorded. Use id for the read and export endpoints below, not the plugin’s external ID.
GET /api/sessions/get
Pass the requiredid query parameter. Returns { "session": {...}, "messages": [...] } for a session owned by the authenticated user. Messages include their parts.
Search endpoint
GET /api/search
{ "results": [...] } with session metadata. Full-text results use id; semantic results use _id; hybrid can include either shape. Read the ID with result.id ?? result._id. Scores, snippets and matchedIn are not returned by this REST API. Semantic and hybrid requests require configured embeddings and a working OpenAI API key.
Context endpoint
GET /api/context
Uses semantic search. Text format returns
{ "text": "...", "sessionCount": 1 }. Messages format returns { "messages": [...], "sessionCount": 1 }; each message contains role, content and session metadata.
Export endpoint
GET /api/export
Exports one owned session. Pass its requiredid and optional format:
Evaluation dataset export is a separate route,
/api/export/evals; it is not selected with /api/export?format=deepeval. Use the dashboard export workflow for evaluation exports while API-key access to that separate route is being verified.
Statistics endpoint
GET /api/stats
ReturnssessionCount, messageCount, totalTokens, totalCost, totalDurationMs and modelUsage. Each model entry includes tokens, cost and sessions. These values depend on data supplied by your plugins.
Health endpoint
GET /health
Public endpoint. Returnsstatus: "ok" and timestamp in milliseconds.
Errors and retries
API errors use{ "error": "message" }. See Error handling. No fixed per-minute API quota is documented by the current implementation. Use bounded requests and exponential backoff for temporary failures; honor Retry-After if an upstream service supplies it.