Base URL: same origin as the Next.js app (e.g. http://localhost:3000).
All extension endpoints require:
Authorization: Bearer <extension_device_token>
Content-Type: application/jsonExcept POST /api/extension/tokens (NextAuth session cookie / browser only).
Auth: NextAuth session (browser only).
Body: { "label"?: string }
Response: { "token": string, "tokenId": string, "label": string | null }
The raw token is shown once. Store it in the extension.
Auth: NextAuth session.
Response: { "items": [{ "id", "label", "createdAt", "lastUsedAt" }] } (no secret values).
Auth: NextAuth session.
Auth: device token.
Response:
{
"userId": "<internal-user-id>",
"hasCursorApiKey": true
}Auth: device token.
Body: { "apiKey": string }
Stores the Cursor API key encrypted at rest. Empty string deletes the stored key.
Response: { "ok": true }
Auth: device token.
Response: { "items": [{ "repoUrl", "startingRef", "lastUsedAt" }] } ordered by lastUsedAt desc.
Auth: device token.
Body: { "repoUrl": string, "startingRef"?: string | null }
Upserts history entry and bumps lastUsedAt.
Response: { "ok": true }
Auth: device token.
Body:
{
"imageBase64": "string (no data: prefix)",
"imageWidth": "number | null",
"imageHeight": "number | null",
"mimeType": "image/png | image/jpeg | image/webp",
"pageUrl": "string",
"pageTitle": "string | null",
"selectedText": "string | null",
"userNote": "string | null",
"repoUrl": "https://github.com/org/repo",
"startingRef": "main | null",
"modelId": "string | null",
"autoCreatePR": true
}Creates a Capture, calls Cursor POST /v1/agents, persists CursorRun.
Response:
{
"runRecordId": "cuid",
"agentId": "bc-...",
"runId": "run-...",
"agentUrl": "https://cursor.com/agents?id=...",
"status": "CREATING"
}Errors: 400 validation, 401 auth, 409 if no Cursor key configured, 502 upstream Cursor error (body includes message).
Auth: device token.
Response:
{
"id": "cuid",
"agentId": "bc-...",
"runId": "run-...",
"status": "CREATING | RUNNING | FINISHED | ERROR | CANCELLED | EXPIRED | UNKNOWN",
"agentUrl": "string | null",
"prUrl": "string | null",
"errorMessage": "string | null",
"updatedAt": "ISO-8601"
}Poll every 2–5s until terminal.