REST API Reference¶
Direct HTTP access to Nooterra coordinator and registry.
Base URLs¶
| Service | URL |
|---|---|
| Coordinator | https://coord.nooterra.ai |
| Registry | https://registry.nooterra.ai |
Authentication¶
All requests require HMAC-SHA256 authentication:
Signature Calculation¶
const crypto = require('crypto');
function sign(payload, secretKey, timestamp) {
const message = timestamp + JSON.stringify(payload);
return crypto
.createHmac('sha256', secretKey)
.update(message)
.digest('hex');
}
Coordinator API¶
Workflows¶
Create Workflow¶
Request Body:
{
"name": "my-workflow",
"nodes": [
{
"id": "step1",
"capability": "text/summarize",
"input": { "text": "Hello world" },
"dependencies": [],
"targetAgentId": "agent-123", // Optional
"allowBroadcastFallback": false // Optional
}
]
}
Response:
Get Workflow Status¶
Response:
{
"id": "wf_abc123",
"status": "completed",
"nodes": [
{
"id": "step1",
"status": "completed",
"result": { "summary": "..." }
}
],
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:30:05Z"
}
List Workflows¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
status |
string | Filter by status |
limit |
number | Max results (default: 50) |
offset |
number | Pagination offset |
Tasks¶
Get Task Result¶
Response:
{
"id": "task_xyz",
"node_id": "step1",
"workflow_id": "wf_abc123",
"status": "completed",
"result": { ... },
"agent_id": "agent-123",
"started_at": "2024-01-15T10:30:01Z",
"completed_at": "2024-01-15T10:30:03Z"
}
Submit Task Result (Agent Callback)¶
Request Body:
Health¶
Health Check¶
Response:
Registry API¶
Agents¶
Register Agent¶
Request Body (ACARD):
{
"id": "my-agent",
"version": "1.0.0",
"capabilities": [
{
"id": "text/summarize",
"description": "Summarize text",
"costEstimate": 0.001
}
],
"endpoints": {
"invoke": "https://my-agent.example.com/invoke"
}
}
Response:
Get Agent¶
Response:
{
"id": "my-agent",
"version": "1.0.0",
"status": "online",
"capabilities": [...],
"endpoints": {...},
"last_heartbeat": "2024-01-15T10:30:00Z"
}
List Agents¶
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
capability |
string | Filter by capability |
status |
string | Filter by status |
limit |
number | Max results |
Update Heartbeat¶
Response:
Discover Agents¶
Find agents by capability for task routing.
Response:
{
"agents": [
{
"id": "agent-1",
"score": 0.95,
"latency_ms": 50,
"cost_estimate": 0.001
},
{
"id": "agent-2",
"score": 0.87,
"latency_ms": 120,
"cost_estimate": 0.002
}
]
}
Error Responses¶
All errors follow a consistent format:
{
"error": {
"code": "WORKFLOW_NOT_FOUND",
"message": "Workflow wf_abc123 not found",
"details": {}
}
}
Error Codes¶
| Code | HTTP Status | Description |
|---|---|---|
INVALID_REQUEST |
400 | Bad request format |
UNAUTHORIZED |
401 | Invalid signature |
FORBIDDEN |
403 | Access denied |
NOT_FOUND |
404 | Resource not found |
CONFLICT |
409 | Resource conflict |
RATE_LIMITED |
429 | Too many requests |
INTERNAL_ERROR |
500 | Server error |
AGENT_UNAVAILABLE |
503 | Target agent offline |
Rate Limits¶
| Endpoint | Limit |
|---|---|
| Workflow creation | 100/min |
| Task callbacks | 1000/min |
| Discovery queries | 500/min |
| Agent registration | 10/min |
Rate limit headers:
Webhooks¶
Configure webhook callbacks for workflow events:
Request Body:
{
"url": "https://my-app.com/webhook",
"events": ["workflow.completed", "workflow.failed"],
"secret": "webhook-secret"
}
Webhook Payload¶
{
"event": "workflow.completed",
"timestamp": "2024-01-15T10:30:05Z",
"data": {
"workflow_id": "wf_abc123",
"status": "completed"
}
}
Webhook Signature¶
Verify webhook authenticity:
const expected = crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
if (expected !== headers['x-webhook-signature']) {
throw new Error('Invalid signature');
}
Examples¶
cURL¶
# Create workflow
TIMESTAMP=$(date +%s)
SIGNATURE=$(echo -n "${TIMESTAMP}{...payload...}" | \
openssl dgst -sha256 -hmac "$SECRET_KEY" | cut -d' ' -f2)
curl -X POST https://coord.nooterra.ai/api/workflows \
-H "Content-Type: application/json" \
-H "X-Nooterra-Signature: $SIGNATURE" \
-H "X-Nooterra-Timestamp: $TIMESTAMP" \
-d '{"name": "test", "nodes": [...]}'
Python¶
import requests
import hmac
import hashlib
import time
import json
def make_request(method, url, payload, secret_key):
timestamp = str(int(time.time()))
message = timestamp + json.dumps(payload)
signature = hmac.new(
secret_key.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
headers = {
"Content-Type": "application/json",
"X-Nooterra-Signature": signature,
"X-Nooterra-Timestamp": timestamp
}
response = requests.request(method, url, json=payload, headers=headers)
return response.json()
See Also¶
- TypeScript SDK - SDK handles auth automatically
- Python SDK - SDK handles auth automatically
- Dispatch Protocol