IAS Docs

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

You can retrieve the full OpenAPI specification URL from a configured CLI:

ias cp openapi-url

The OpenAPI spec is also available directly:

GET https://<deployment>.convex.site/control-plane/openapi.json

Authentication

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:

MethodUse CaseHow to Obtain
Device login tokenDeveloper machinesias auth login (stored at ~/.ias/auth.json)
Service tokenCI/CD automationSet IAS_CONTROL_PLANE_SERVICE_TOKEN env var in Convex
Dev-only unauthLocal development onlySet 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:

CodeMeaning
200Success
400Bad request (missing or invalid parameters)
401Unauthorized (missing, invalid, or expired token)
500Server error

Health Check

GET /control-plane/health

Returns 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/resolve

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

Initiate 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/poll

Poll 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/revoke

Revoke the bearer token used in the current request. Used by ias auth logout.

Worker Endpoints

Worker Heartbeat

POST /control-plane/v1/workers/heartbeat

Register 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/resolve

Resolve 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/get

Retrieve repository metadata by ID.

Request body:

{
  "workspaceId": "...",
  "repoId": "..."
}

Upsert Repository

POST /control-plane/v1/repos/upsert

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

List jobs filtered by workspace and optional status.

Request body:

{
  "workspaceId": "...",
  "status": "pending"
}

Enqueue Job

POST /control-plane/v1/jobs/enqueue

Create 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-next

Claim 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/heartbeat

Extend 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/complete

Report 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-job

Retrieve 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-resolution

Resolve 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-promotion

Create 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/upsert

Create 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/upsert

Update 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-next

Claim the next available cloud AI job. Returns the job definition and a lease.

Heartbeat Cloud AI Job

POST /control-plane/v1/cloud-ai-jobs/heartbeat

Extend the lease on a running cloud AI job.

Complete Cloud AI Job

POST /control-plane/v1/cloud-ai-jobs/complete

Report 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-v1

Build 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-v1

Resolve 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/ingest

Ingest 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 event are scheduled immediately
  • Events respect the workspace data policy for content storage

Slack Events

POST /integrations/slack/events/v1

Receive 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-url

Retrieve 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:

  1. Start up -- Register with the control plane by sending a heartbeat with capabilities
  2. Poll -- Call claim-next in a loop to check for available jobs
  3. Claim -- Receive a job and its metadata, including the lease duration
  4. Execute -- Run the job locally against the repository checkout
  5. Heartbeat -- Send periodic heartbeats to maintain the lease during execution
  6. Complete -- Report the outcome (done/failed/blocked) with evidence
  7. 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.

On this page