Overview
The Control Plane API provides programmatic access to SO1’s orchestration layer, allowing you to execute agents, manage workflows, trigger automations, and monitor system health.
Base URL : https://api.so1.io/v1/control-planeAll Control Plane endpoints require authentication via Bearer token.
API Architecture
The Control Plane API is organized into four main categories:
Quick Start
Execute an Agent
curl -X POST https://api.so1.io/v1/control-plane/agents/execute \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agentId": "mintlify-author",
"taskType": "create-agent-reference",
"context": {
"agentName": "workflow-architect",
"sourcePath": "/agents/automation/workflow-architect.md"
},
"forge": {
"stage": "IMPLEMENT",
"validateGates": true
}
}'
Trigger a Workflow
curl -X POST https://api.so1.io/v1/control-plane/workflows/trigger \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"workflowId": "deployment-pipeline",
"environment": "production",
"payload": {
"service": "api-gateway",
"version": "v2.4.1"
}
}'
Check Orchestration Status
curl -X GET https://api.so1.io/v1/control-plane/orchestration/status/orch-abc123 \
-H "Authorization: Bearer YOUR_API_KEY"
Authentication
All Control Plane API requests require a valid API key passed as a Bearer token:
Authorization : Bearer so1_key_abc123xyz789
Keep Your API Keys Secret : Never commit API keys to version control or expose them in client-side code.
See Authentication for detailed API key management.
Common Request Patterns
Synchronous vs Asynchronous Execution
Most Control Plane operations are asynchronous by default, returning immediately with a task ID:
Asynchronous (Default)
Synchronous (Blocking)
const response = await fetch ( 'https://api.so1.io/v1/control-plane/agents/execute' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
agentId: 'hono-backend' ,
taskType: 'implement-endpoint' ,
context: { endpoint: '/api/users' , method: 'POST' }
})
});
const { taskId , status } = await response . json ();
// Returns immediately with taskId: "task-xyz789"
// Poll /tasks/{taskId} for completion
Timeout Limits : Synchronous requests have a maximum timeout of 5 minutes (300 seconds). For long-running operations, use asynchronous mode.
Polling for Results
For asynchronous operations, poll the task status endpoint:
async function waitForCompletion ( taskId : string ) : Promise < any > {
const maxAttempts = 60 ; // 5 minutes with 5s intervals
for ( let attempt = 0 ; attempt < maxAttempts ; attempt ++ ) {
const response = await fetch (
`https://api.so1.io/v1/control-plane/tasks/ ${ taskId } ` ,
{ headers: { 'Authorization' : `Bearer ${ API_KEY } ` } }
);
const task = await response . json ();
if ( task . status === 'completed' ) {
return task . result ;
} else if ( task . status === 'failed' ) {
throw new Error ( task . error . message );
}
// Still running, wait and retry
await new Promise ( resolve => setTimeout ( resolve , 5000 ));
}
throw new Error ( 'Task timeout after 5 minutes' );
}
const taskId = 'task-xyz789' ;
const result = await waitForCompletion ( taskId );
Webhooks for Completion Notifications
Instead of polling, register a webhook to receive completion notifications:
const response = await fetch ( 'https://api.so1.io/v1/control-plane/agents/execute' , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
agentId: 'railway-deployer' ,
taskType: 'deploy-service' ,
context: { service: 'api' , environment: 'production' },
webhook: {
url: 'https://your-app.com/webhooks/so1' ,
events: [ 'task.completed' , 'task.failed' ],
secret: 'whsec_abc123xyz789'
}
})
});
Your webhook endpoint will receive:
{
"event" : "task.completed" ,
"taskId" : "task-xyz789" ,
"agentId" : "railway-deployer" ,
"timestamp" : "2024-03-10T15:30:00Z" ,
"result" : {
"deploymentId" : "dep-abc123" ,
"status" : "live" ,
"url" : "https://api-production.railway.app"
}
}
See Webhook Security for signature verification.
All Control Plane API responses follow a consistent format:
Success Response
{
"success" : true ,
"data" : {
"taskId" : "task-xyz789" ,
"status" : "running" ,
"createdAt" : "2024-03-10T15:30:00Z"
},
"meta" : {
"requestId" : "req-abc123" ,
"timestamp" : "2024-03-10T15:30:00.123Z"
}
}
Error Response
{
"success" : false ,
"error" : {
"code" : "AGENT_NOT_FOUND" ,
"message" : "Agent 'invalid-agent' does not exist" ,
"details" : {
"agentId" : "invalid-agent" ,
"availableAgents" : [ "mintlify-author" , "hono-backend" , "..." ]
}
},
"meta" : {
"requestId" : "req-abc123" ,
"timestamp" : "2024-03-10T15:30:00.123Z"
}
}
Rate Limits
Control Plane API endpoints have tier-based rate limits:
Tier Requests/Min Concurrent Executions Free 10 2 Starter 60 10 Professional 300 50 Enterprise 1,000 200
See Rate Limits for detailed policies.
SDKs and Libraries
Official SDKs are available for popular languages:
SDK Example
TypeScript/Node.js
Python
Go
import { SO1 } from '@so1/sdk' ;
const client = new SO1 ({
apiKey: process . env . SO1_API_KEY
});
const execution = await client . agents . execute ({
agentId: 'mintlify-author' ,
taskType: 'create-agent-reference' ,
context: {
agentName: 'workflow-architect' ,
sourcePath: '/agents/automation/workflow-architect.md'
}
});
console . log ( `Task ID: ${ execution . taskId } ` );
// Wait for completion
const result = await execution . waitForCompletion ();
console . log ( 'Agent output:' , result . output );
API Endpoints