Skip to main content

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:
For your own deployment, use its HTTP actions URL (.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:
Generate API keys from the Settings page in the dashboard. Keys start with osk_ and are tied to your user account.
API keys provide full access to your account data. Do not commit them to version control or share them publicly.

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 on externalId, so calling this multiple times with the same externalId is safe. Request body:
Required fields: Optional fields: Response:

POST /sync/message

Create or update a message within a session. The session is identified by sessionExternalId and will be auto-created if it does not exist. Request body:
Required fields: 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:
Response:
The batch response counts inserted and updated items; unchanged retries are excluded. Inspect 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 required id query parameter. Returns { "session": {...}, "messages": [...] } for a session owned by the authenticated user. Messages include their parts.

Search endpoint

GET /api/search

Returns { "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 required id 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

Returns sessionCount, 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. Returns status: "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.