Operations API Endpoints

Complete reference for notifications, merging, analytics, trash, sprint chains, recurring tasks, branches, pull requests, and inbox REST API endpoints in CodeCourier.

14 min read
apinotificationsmerging

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-count

Response:

{ "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) -- unread or all (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_.../read

PUT /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-all

DELETE /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/list

POST /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/start

Required: 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 string
  • service (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 range
  • endDate (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/list

POST /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_.../restore

DELETE /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 chain
  • currentSprintIndex (number) -- Zero-based index of the currently executing sprint
  • resumeFromSprint (number | null) -- If set, the chain will restart from this sprint index on the next run attempt
  • sprintPrUrls (string[]) -- Ordered list of PR URLs generated by each completed sprint
  • workflowId (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-chains

GET /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-chains

Body fields:

  • workflowId (string, required) -- Workflow blueprint to run for each sprint
  • sprintRange ([number, number], required) -- Start and end sprint numbers (inclusive)
  • prompt (string, required) -- Master task description shared across all sprints
  • githubRepoUrl (string, required) -- Target repository URL
  • branchName (string, optional) -- Base branch to work from
  • resumeFromSprint (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 interpreting scheduledHour and scheduledMinute
  • scheduledHour (0-23) -- Hour of day in the specified timezone when the task fires
  • scheduledMinute (0-59) -- Minute within the hour when the task fires
  • nextRunAt (ISO timestamp) -- UTC datetime of the next scheduled execution
  • isActive (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-tasks

GET /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-tasks

Body fields:

  • title (string, required) -- Human-readable task name
  • prompt (string, required) -- The task prompt sent to the AI agent on each execution
  • frequency (string, required) -- Recurrence frequency: daily, every_other_day, weekly, biweekly, or monthly
  • targetWorkflowId (string, required) -- Workflow blueprint to use for each run
  • timezone (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_.../toggle

Body fields:

  • isActive (boolean, required) -- true to activate, false to deactivate

Info

When you reactivate a task, 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

This endpoint calls the GitHub API on each request. If the project has not configured a GitHub provider key, it returns a 400 error. Avoid high-frequency polling; cache branch lists client-side and refresh on demand.

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_ci
  • runId (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_.../merge

Optional body fields:

  • mergeStrategy (string) -- Merge strategy: merge, squash, or rebase (default: squash)
  • skipCiCheck (boolean) -- Force merge even if CI has not passed (use with caution)

Response (201 Created):

{ "data": { "mergeJobId": "...", "status": "running" } }

Warning

Setting 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.