Operations API Endpoints
Complete reference for notifications, merging, analytics, trash, sprint chains, recurring tasks, branches, pull requests, and inbox REST API endpoints in CodeCourier.
The Operations API covers cross-cutting concerns: notifications, PR merging, usage analytics, trash management, sprint chains, recurring tasks, GitHub branch management, pull request operations, and inbox management. These 28 endpoints help you monitor activity, merge completed work, track costs, schedule recurring automation, and manage deleted resources.
Notifications
GET /api/v1/notifications/list
List notifications for the current user and project.
Query parameters:
filter(optional) -- Filter type (e.g., unread, all)
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/notifications/list?filter=unread"Notification types include: run_completed, run_failed, pr_created, pr_merged, pr_failed, member_joined, workflow_completed, sprint_completed, sprint_failed.
GET /api/v1/notifications/unread-count
Get the count of unread notifications.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/notifications/unread-countResponse:
{ "data": { "count": 5 } }POST /api/v1/notifications/mark-read
Mark a single notification as read.
{ "notificationId": "..." }POST /api/v1/notifications/mark-all-read
Mark all notifications as read for the project. No body required.
POST /api/v1/notifications/dismiss
Dismiss a notification (hides it from the list).
{ "notificationId": "..." }Inbox / Notification REST Endpoints
In addition to the legacy /notifications/* endpoints above, the API exposes a RESTful inbox interface under /api/v1/notifications using standard HTTP verbs:
GET /api/v1/notifications
List all notifications for the project using REST-style URL.
Query parameters:
filter(optional) --unreadorall(default:all)limit(optional) -- Max results (default: 50)
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/notifications?filter=unread&limit=20"PUT /api/v1/notifications/:id/read
Mark a specific notification as read.
curl -X PUT -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/notifications/notif_.../readPUT /api/v1/notifications/read-all
Mark all notifications for the project as read. No body required.
curl -X PUT -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/notifications/read-allDELETE /api/v1/notifications/:id
Dismiss and remove a specific notification.
curl -X DELETE -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/notifications/notif_...Merging
GET /api/v1/merging/list
List all merge agent runs for the project.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/merging/listPOST /api/v1/merging/start
Start a merge agent that combines multiple pull requests into one. The merge agent provisions a sandbox, fetches all PRs, resolves conflicts, and creates a unified PR.
curl -X POST -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"pullRequests": [
{"prUrl": "https://github.com/org/repo/pull/1", "prNumber": 1},
{"prUrl": "https://github.com/org/repo/pull/2", "prNumber": 2}
],
"baseBranch": "main",
"config": {}
}' \
https://<deployment>.convex.site/api/v1/merging/startRequired: pullRequests (non-empty array of PR objects).
Optional: baseBranch, config.
Response (201 Created):
{ "data": { "id": "...", "status": "running" } }Analytics
GET /api/v1/analytics/usage
Retrieve usage records (compute, tokens, API calls) with date range and service filtering.
Query parameters:
startDate(optional) -- ISO date string (e.g., 2024-01-01)endDate(optional) -- ISO date stringservice(optional) -- Filter by service (e.g., e2b, anthropic, openai)
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/analytics/usage?startDate=2024-01-01&endDate=2024-01-31"GET /api/v1/analytics/daily-stats
Get daily aggregated statistics for the project.
Query parameters:
startDate(optional) -- Start of date rangeendDate(optional) -- End of date range
GET /api/v1/analytics/counters
Get current project counters (total runs, active sandboxes, pending issues, etc.).
Trash Management
GET /api/v1/trash/list
List all soft-deleted resources across all entity types (runs, sandboxes, workflows, issue sessions, learnings, etc.).
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/trash/listPOST /api/v1/trash/restore
Restore a soft-deleted resource from trash.
{
"entityType": "run",
"entityId": "..."
}Valid entityType values: run, sandbox, workflow, learning, issueSession.
POST /api/v1/trash/permanent-delete
Permanently delete a resource from trash. Cannot be undone.
{
"entityType": "run",
"entityId": "..."
}GET /api/v1/trash
REST-style endpoint to list soft-deleted items. Returns the same data as GET /api/v1/trash/list. Supports an optional type query parameter to filter by entity type.
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/trash?type=run"POST /api/v1/trash/:type/:id/restore
REST-style restore. :type is the entity type (e.g., run) and :id is the entity ID.
curl -X POST -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/trash/run/r_.../restoreDELETE /api/v1/trash/:type/:id
REST-style permanent delete. Irreversibly removes the entity from the system.
curl -X DELETE -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/trash/run/r_...Sprint Chains
Sprint chains orchestrate multi-sprint AI work, executing a series of sequential runs across numbered sprints. A sprint chain can be paused, resumed from a specific sprint index, and tracks its generated PR URLs per sprint.
Sprint Chain Object
{
"id": "sc_...",
"status": "running",
"sprintRange": [1, 5],
"currentSprintIndex": 2,
"resumeFromSprint": null,
"sprintPrUrls": [
"https://github.com/org/repo/pull/10",
"https://github.com/org/repo/pull/11"
],
"workflowId": "wf_...",
"createdAt": "2024-01-15T10:00:00Z"
}Sprint chain status values: pending, running, completed, failed, cancelled.
sprintRange([start, end]) -- The first and last sprint numbers in the chaincurrentSprintIndex(number) -- Zero-based index of the currently executing sprintresumeFromSprint(number | null) -- If set, the chain will restart from this sprint index on the next run attemptsprintPrUrls(string[]) -- Ordered list of PR URLs generated by each completed sprintworkflowId(string) -- The workflow blueprint used for each sprint execution
GET /api/v1/sprint-chains
List all sprint chains for the project.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/sprint-chainsGET /api/v1/sprint-chains/:id
Get a single sprint chain by ID, including full sprint metadata and PR URLs.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/sprint-chains/sc_...POST /api/v1/sprint-chains
Create and start a new sprint chain.
curl -X POST -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"workflowId": "wf_...",
"sprintRange": [1, 5],
"prompt": "Migrate all REST API handlers to use the new validation layer",
"githubRepoUrl": "https://github.com/org/repo",
"branchName": "feature/validation-migration"
}' \
https://<deployment>.convex.site/api/v1/sprint-chainsBody fields:
workflowId(string, required) -- Workflow blueprint to run for each sprintsprintRange([number, number], required) -- Start and end sprint numbers (inclusive)prompt(string, required) -- Master task description shared across all sprintsgithubRepoUrl(string, required) -- Target repository URLbranchName(string, optional) -- Base branch to work fromresumeFromSprint(number, optional) -- Start execution from a specific sprint index (for resuming interrupted chains)
Response (201 Created):
{ "data": { "id": "sc_...", "status": "running" } }DELETE /api/v1/sprint-chains/:id
Cancel and delete a sprint chain. If the chain is currently running, the active sprint is allowed to finish before the chain is marked cancelled.
curl -X DELETE -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/sprint-chains/sc_...Recurring Tasks
Recurring tasks let you schedule a workflow prompt to run automatically on a fixed cadence -- daily, weekly, monthly, and more. Each firing creates a new run with the scheduledFor and recurrencePattern fields populated.
Recurring Task Object
{
"id": "rt_...",
"title": "Daily dependency audit",
"description": "Check for outdated or vulnerable npm packages",
"prompt": "Run npm audit and npm outdated. Create issues for any critical vulnerabilities found.",
"frequency": "daily",
"targetWorkflowId": "wf_...",
"isActive": true,
"timezone": "America/Chicago",
"scheduledHour": 8,
"scheduledMinute": 0,
"nextRunAt": "2024-01-16T14:00:00Z"
}Frequency values: daily, every_other_day, weekly, biweekly, monthly.
timezone(IANA timezone string) -- Timezone for interpretingscheduledHourandscheduledMinutescheduledHour(0-23) -- Hour of day in the specified timezone when the task firesscheduledMinute(0-59) -- Minute within the hour when the task firesnextRunAt(ISO timestamp) -- UTC datetime of the next scheduled executionisActive(boolean) -- Whether the task is currently enabled; inactive tasks are not executed
GET /api/v1/recurring-tasks
List all recurring tasks for the project.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/recurring-tasksGET /api/v1/recurring-tasks/:id
Get a single recurring task by ID.
curl -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/recurring-tasks/rt_...POST /api/v1/recurring-tasks
Create a new recurring task.
curl -X POST -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Weekly bundle size check",
"description": "Ensure the production bundle stays under 200KB",
"prompt": "Run the build and measure bundle size. If total JS exceeds 200KB, open an issue listing the top 5 contributors by size.",
"frequency": "weekly",
"targetWorkflowId": "wf_...",
"timezone": "UTC",
"scheduledHour": 6,
"scheduledMinute": 0
}' \
https://<deployment>.convex.site/api/v1/recurring-tasksBody fields:
title(string, required) -- Human-readable task nameprompt(string, required) -- The task prompt sent to the AI agent on each executionfrequency(string, required) -- Recurrence frequency:daily,every_other_day,weekly,biweekly, ormonthlytargetWorkflowId(string, required) -- Workflow blueprint to use for each runtimezone(string, required) -- IANA timezone string (e.g.,America/New_York,UTC)scheduledHour(number, required) -- Hour to fire (0-23, in the specified timezone)scheduledMinute(number, required) -- Minute to fire (0-59)description(string, optional) -- Extended description for documentation purposes
Response (201 Created):
{ "data": { "id": "rt_...", "isActive": true, "nextRunAt": "2024-01-16T06:00:00Z" } }PUT /api/v1/recurring-tasks/:id
Update a recurring task. All fields are optional; only the provided fields are changed. Updating schedule-related fields (frequency, scheduledHour, scheduledMinute, timezone) automatically recomputes nextRunAt.
curl -X PUT -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{
"frequency": "biweekly",
"scheduledHour": 9,
"timezone": "Europe/London"
}' \
https://<deployment>.convex.site/api/v1/recurring-tasks/rt_...DELETE /api/v1/recurring-tasks/:id
Permanently delete a recurring task. Active runs already in progress are not affected.
curl -X DELETE -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/recurring-tasks/rt_...PUT /api/v1/recurring-tasks/:id/toggle
Activate or deactivate a recurring task. An inactive task is preserved but will not fire on its schedule. Use this to temporarily pause automation without deleting the configuration.
# Deactivate
curl -X PUT -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{ "isActive": false }' \
https://<deployment>.convex.site/api/v1/recurring-tasks/rt_.../toggle
# Reactivate
curl -X PUT -H "Authorization: Bearer cc_live_..." \
-H "Content-Type: application/json" \
-d '{ "isActive": true }' \
https://<deployment>.convex.site/api/v1/recurring-tasks/rt_.../toggleBody fields:
isActive(boolean, required) --trueto activate,falseto deactivate
Info
nextRunAtis recalculated from the current time using the task's frequency and schedule. The task will not retroactively fire for any executions missed while it was inactive.Branches
The Branches API surfaces GitHub branches for the project's configured repository, allowing you to inspect and clean up feature branches created by AI runs.
GET /api/v1/branches
List GitHub branches for the project's repository. Returns branch metadata including the last commit SHA, author, and timestamp.
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/branches"
# → {
# "data": [
# {
# "name": "feature/dark-mode",
# "sha": "abc123...",
# "author": "codecourier[bot]",
# "committedAt": "2024-01-15T10:30:00Z",
# "isProtected": false
# }
# ]
# }Query parameters:
prefix(optional) -- Filter branches by name prefix (e.g.,feature/)limit(optional) -- Max results (default: 100)
Warning
DELETE /api/v1/branches/:name
Delete a GitHub branch by name. The branch name should be URL-encoded if it contains slashes (e.g., feature%2Fdark-mode). Protected branches and the default branch cannot be deleted via this endpoint.
curl -X DELETE -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/branches/feature%2Fdark-mode"Pull Requests
The Pull Requests API lets you list open PRs across runs and trigger automated merge operations.
GET /api/v1/pull-requests
List pull requests for the project, including their CI check status. Results are sourced from CodeCourier's run records rather than polling GitHub directly, so they reflect PRs created by AI runs within the platform.
curl -H "Authorization: Bearer cc_live_..." \
"https://<deployment>.convex.site/api/v1/pull-requests"Query parameters:
status(optional) -- Filter by PR status:creating,created,failed,skipped,merged,blocked_on_cirunId(optional) -- Get the PR for a specific run
Response:
{
"data": [
{
"runId": "r_...",
"runName": "Add dark mode toggle",
"prUrl": "https://github.com/org/repo/pull/42",
"prNumber": 42,
"prStatus": "blocked_on_ci",
"ciChecks": {
"status": "failed",
"checkedAt": "2024-01-15T10:30:00Z",
"checks": [
{ "name": "test", "status": "failure", "conclusion": "failure" }
]
}
}
]
}POST /api/v1/pull-requests/:id/merge
Trigger the merge agent for a specific pull request. The :id parameter is the run ID associated with the PR, not the PR number. The merge agent provisions a sandbox, verifies CI status, and performs the merge.
curl -X POST -H "Authorization: Bearer cc_live_..." \
https://<deployment>.convex.site/api/v1/pull-requests/r_.../mergeOptional body fields:
mergeStrategy(string) -- Merge strategy:merge,squash, orrebase(default:squash)skipCiCheck(boolean) -- Force merge even if CI has not passed (use with caution)
Response (201 Created):
{ "data": { "mergeJobId": "...", "status": "running" } }Warning
skipCiCheck: true bypasses CI gate enforcement. Only use this if you are certain the failure is a flaky test or unrelated to the changes in the PR.