Control Plane HTTP API
Reference for the IAS control plane HTTP API endpoints, authentication, and usage patterns for workers and integrations.
The IAS control plane exposes an HTTP API for workers, runners, and integrations to communicate with the Console backend. This API is hosted on Convex HTTP routes and is the only supported interface for machine-to-machine communication with IAS. Workers and the hybrid runner use this API internally -- you do not need to call it directly unless you are building custom tooling or integrations.
Base URL
The control plane API is served from the Convex site URL (not the cloud URL):
https://<deployment>.convex.site/control-planeYou can retrieve the full OpenAPI specification URL from a configured CLI:
ias cp openapi-urlThe OpenAPI spec is also available directly:
GET https://<deployment>.convex.site/control-plane/openapi.jsonAuthentication
All requests (except health check and the OpenAPI spec) must include an Authorization header with a bearer token:
Authorization: Bearer <token>Three authentication methods are supported:
| Method | Use Case | How to Obtain |
|---|---|---|
| Device login token | Developer machines | ias auth login (stored at ~/.ias/auth.json) |
| Service token | CI/CD automation | Set IAS_CONTROL_PLANE_SERVICE_TOKEN env var in Convex |
| Dev-only unauth | Local development only | Set IAS_DEV_ALLOW_UNAUTH=true in Convex env |
For details on each method, see Authentication.
Request and Response Format
All endpoints accept JSON request bodies (where applicable) and return JSON responses. Request bodies must not exceed 256 KB.
Successful responses include "ok": true:
{
"ok": true,
"data": { ... }
}Error responses include a descriptive error code:
{
"ok": false,
"error": "DESCRIPTIVE_ERROR_CODE"
}Standard HTTP status codes are used:
| Code | Meaning |
|---|---|
200 | Success |
400 | Bad request (missing or invalid parameters) |
401 | Unauthorized (missing, invalid, or expired token) |
500 | Server error |
Health Check
GET /control-plane/healthReturns the service health status. No authentication required.
Response:
{ "ok": true }Use this endpoint to verify connectivity before attempting authenticated operations.
Workspace Endpoints
Resolve Workspace
POST /control-plane/v1/workspaces/resolveResolve a workspace by its slug. Returns the workspace ID and metadata if found.
Request body:
{ "slug": "your-workspace" }Response:
{
"ok": true,
"workspaceId": "...",
"workspace": { ... }
}Returns workspaceId: null if no workspace matches the slug, or if the authenticated user does not have access to the workspace.
Authentication Endpoints
These endpoints implement the device login flow used by ias auth login.
Start Device Auth
POST /control-plane/v1/auth/device/startInitiate a device authentication session. The CLI calls this to create a short-lived session that the user approves in their browser.
Request body:
{
"workspaceSlug": "your-workspace",
"machineName": "optional-machine-name"
}Response:
{
"ok": true,
"deviceId": "...",
"deviceSecret": "...",
"approvalUrl": "https://console.example.com/auth/device?id=..."
}Poll Device Auth
POST /control-plane/v1/auth/device/pollPoll for the result of a device auth session. The CLI calls this repeatedly until the user approves (or the session expires).
Request body:
{
"deviceId": "...",
"deviceSecret": "..."
}Response (pending):
{ "ok": true, "status": "pending" }Response (approved):
{
"ok": true,
"status": "approved",
"token": "bearer-token-value",
"workspaceId": "...",
"workspaceSlug": "..."
}Revoke Token
POST /control-plane/v1/auth/token/revokeRevoke the bearer token used in the current request. Used by ias auth logout.
Worker Endpoints
Worker Heartbeat
POST /control-plane/v1/workers/heartbeatRegister or update a worker's online status. Workers send periodic heartbeats to indicate they are available for work. The heartbeat includes the worker's capabilities and display metadata.
Request body:
{
"workspaceId": "...",
"displayName": "my-machine",
"machineFingerprint": "unique-machine-id",
"status": "online",
"capabilities": {
"executionModes": ["cli", "hybrid"],
"models": ["codex"],
"canWrite": true
}
}Response:
{ "ok": true, "workerId": "..." }The Console uses heartbeat data to show which workers are online and to match jobs with workers that have the required capabilities.
Repository Endpoints
Resolve Repository
POST /control-plane/v1/repos/resolveResolve a repository by its remote URL hash (SHA-256 of the normalized Git remote origin URL). This avoids transmitting the actual repository URL to the cloud.
Request body:
{
"workspaceId": "...",
"remoteUrlHash": "sha256-hex-string"
}Get Repository
POST /control-plane/v1/repos/getRetrieve repository metadata by ID.
Request body:
{
"workspaceId": "...",
"repoId": "..."
}Upsert Repository
POST /control-plane/v1/repos/upsertRegister or update a repository record. Used by ias repo link to map local checkouts to Console repositories. Creates a new record if the remoteUrlHash is not found, or updates the existing record.
Request body:
{
"workspaceId": "...",
"remoteUrlHash": "sha256-hex-string",
"label": "my-project",
"status": "active"
}Job Endpoints
These endpoints manage the job queue -- the core mechanism for coordinating work between the Console and local workers.
List Jobs
POST /control-plane/v1/jobs/listList jobs filtered by workspace and optional status.
Request body:
{
"workspaceId": "...",
"status": "pending"
}Enqueue Job
POST /control-plane/v1/jobs/enqueueCreate a new job in the queue. The job will be available for workers to claim.
Request body:
{
"workspaceId": "...",
"repoId": "...",
"runId": "(optional)",
"kind": "work",
"role": "implementer",
"prompt": "Implement the user settings page",
"requirements": "(optional)",
"priority": 0
}Job kinds include: install_ias, create_run, context_architect, apply_decision, update_git_policy, git_repair, work, and pr_review.
Claim Next Job
POST /control-plane/v1/jobs/claim-nextClaim the next available job matching the worker's capabilities. Returns the job definition and a lease, or an empty response if no jobs are available.
Request body:
{
"workspaceId": "...",
"workerId": "...",
"leaseMs": 600000
}The leaseMs parameter sets the initial lease duration in milliseconds. The worker must heartbeat before the lease expires to retain the job.
Job Heartbeat
POST /control-plane/v1/jobs/heartbeatExtend the lease on a running job. Workers must heartbeat periodically to prevent the job from being reclaimed.
Request body:
{
"workspaceId": "...",
"jobId": "...",
"workerId": "...",
"leaseMs": 600000,
"message": "(optional progress message)"
}Complete Job
POST /control-plane/v1/jobs/completeReport a job as completed. The outcome can be done, failed, or blocked.
Request body:
{
"workspaceId": "...",
"jobId": "...",
"workerId": "...",
"runId": "(optional)",
"outcome": "done",
"message": "Implemented user settings page",
"outcomeReason": "(optional)",
"evidence": {
"commitSha": "abc123...",
"changedFiles": ["src/settings.tsx"]
}
}Job Event Endpoints
List Job Events
POST /control-plane/v1/job-events/list-for-jobRetrieve the event timeline for a specific job. Events include enqueued, claimed, heartbeat, log, completed, failed, blocked, canceled, and recovered.
Request body:
{
"workspaceId": "...",
"jobId": "...",
"limit": 50
}Decision Request Endpoints
These endpoints manage decision requests (uncertainties) -- the mechanism agents use to ask humans for input.
Add Resolution
POST /control-plane/v1/uncertainties/add-resolutionResolve a decision request (uncertainty) with an answer.
Request body:
{
"workspaceId": "...",
"uncertaintyId": "...",
"mode": "answered",
"value": "Use PostgreSQL for the database",
"commitSha": "(optional)",
"confidence": 0.9,
"createdByJobId": "(optional)"
}Create with Auto-Promotion
POST /control-plane/v1/uncertainties/create-with-auto-promotionCreate a new decision request. If the request meets auto-promotion criteria, it is promoted to a full decision request visible in the Inbox. Supports uncertainty kinds: missing_fact, choice, constraint, approval, config, and risk.
Request body:
{
"workspaceId": "...",
"runId": "...",
"jobId": "(optional)",
"prompt": "Which database engine should we use?",
"kind": "choice",
"context": "The project needs a relational database...",
"confidence": 0.6,
"impact": "high",
"reversibility": "hard",
"assumedValue": "PostgreSQL",
"assumedReasoning": "Most common choice for this stack",
"autoPromoteThreshold": 0.8
}Response:
{
"ok": true,
"uncertaintyId": "...",
"decisionRequestId": "...",
"promoted": true
}Run Endpoints
Upsert Run (v1)
POST /control-plane/v1/runs/upsertCreate or update a run (goal) record. The v1 endpoint resolves runs by workspace, repository, and run reference.
Request body:
{
"workspaceId": "...",
"repoId": "...",
"runRef": "20260214-user-settings",
"status": "in_progress",
"currentMilestone": "implementation",
"runStatePath": "docs/ias/runs/20260214-user-settings/state.json"
}Upsert Run (v2)
POST /control-plane/v2/runs/upsertUpdate a run record by ID. The v2 endpoint takes a runId directly instead of resolving by reference.
Request body:
{
"workspaceId": "...",
"runId": "...",
"status": "done",
"currentMilestone": "complete"
}Cloud AI Job Endpoints
These endpoints support cloud-executed AI jobs (local executor variant).
Claim Next Cloud AI Job
POST /control-plane/v1/cloud-ai-jobs/claim-nextClaim the next available cloud AI job. Returns the job definition and a lease.
Heartbeat Cloud AI Job
POST /control-plane/v1/cloud-ai-jobs/heartbeatExtend the lease on a running cloud AI job.
Complete Cloud AI Job
POST /control-plane/v1/cloud-ai-jobs/completeReport a cloud AI job as completed with the outcome and result.
Context Pack Endpoints
Context packs assemble relevant context from the Context Lake for agent consumption during job execution.
Build Run Context Pack
POST /control-plane/v1/context-packs/build-run-v1Build a context pack for a run. Assembles project context items, knowledge artifacts, and integration-sourced content relevant to the run. Supports expansion hints (e.g., fresh_v1 for live Gmail thread fetching).
Request body:
{
"workspaceId": "...",
"runId": "...",
"requestedContextItemIds": ["(optional specific item IDs)"],
"expansionHints": ["fresh_v1"]
}Resolve Run Context Pack
POST /control-plane/v1/context-packs/resolve-run-v1Resolve and return the content of a context pack, including cached text extracts and optionally fetched live content from integrations.
Integration Endpoints
Event Ingestion
POST /integrations/events/v1/ingestIngest integration events (from webhooks or polling) into the Context Lake. Events are processed according to the workspace's data policy. This endpoint is separate from the control plane and uses its own authentication.
Authentication:
x-ias-integration-event-secret: <secret>Where <secret> matches the IAS_INTEGRATION_EVENT_SECRET Convex environment variable.
Behavior:
- The payload is workspace-scoped and idempotent (via
idempotencyKey) - Matching run triggers of type
eventare scheduled immediately - Events respect the workspace data policy for content storage
Slack Events
POST /integrations/slack/events/v1Receive inbound Slack Events API payloads. These are processed as integration events and routed into the Context Lake.
Upload Endpoints
Get Download URL
POST /control-plane/v1/uploads/get-download-urlRetrieve a temporary download URL for an uploaded file. Used by workers to download requirement document attachments from the Console into the local repository during job execution.
Request body:
{
"workspaceId": "...",
"uploadId": "..."
}Worker Usage Patterns
A typical worker lifecycle follows this loop:
- Start up -- Register with the control plane by sending a heartbeat with capabilities
- Poll -- Call
claim-nextin a loop to check for available jobs - Claim -- Receive a job and its metadata, including the lease duration
- Execute -- Run the job locally against the repository checkout
- Heartbeat -- Send periodic heartbeats to maintain the lease during execution
- Complete -- Report the outcome (done/failed/blocked) with evidence
- Loop -- Return to step 2
The ias worker start and ias runner start commands implement this lifecycle automatically. The worker handles setup jobs while the runner handles AI execution jobs.
Multi-Developer Setup
Each developer runs their own worker with their own configuration. Workers advertise which repositories they can serve (via repos.mappings in the worker config), and the control plane only assigns jobs for those repositories. This means:
- Multiple developers can have workers online simultaneously
- Each worker only claims jobs for repositories it has checked out locally
- There is no conflict between workers -- the lease mechanism ensures exactly-once execution
For more details, see Execution Modes and Authentication.