Agents receive events via a callback URL (push) or can poll for pending executions. Each agent is scoped to an organization and optionally to a specific project or set of task types.
List Agents
GET /api/v1/agents/
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
cursor | string | No | Cursor for pagination (query parameter) |
limit | integer | No | Number of results per page (query parameter) |
Request
curl "https://api.avala.ai/api/v1/agents/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY"
import requests
response = requests.get(
"https://api.avala.ai/api/v1/agents/",
headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
)
agents = response.json()["results"]
const response = await fetch(
"https://api.avala.ai/api/v1/agents/",
{
headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
}
);
const { results } = await response.json();
req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/agents/", nil)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
Response
{
"next": null,
"previous": null,
"results": [
{
"uid": "b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f",
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"is_active": true,
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"],
"created_at": "2025-03-15T10:00:00Z",
"updated_at": "2025-03-15T10:00:00Z"
}
]
}
Fields
| Field | Type | Description |
|---|---|---|
uid | string (UUID) | Unique identifier for the agent registration |
name | string | Display name of the agent |
description | string | Human-readable description of what the agent does |
events | array | List of event types this agent subscribes to |
callback_url | string | HTTPS URL where events are delivered (push mode) |
is_active | boolean | Whether the agent is currently enabled |
project | string (UUID) | null | Project this agent is scoped to, or null for org-wide |
task_types | array | Task types this agent handles (empty means all types) |
created_at | string (datetime) | ISO 8601 timestamp of when the agent was registered |
updated_at | string (datetime) | ISO 8601 timestamp of the last update |
Register Agent
POST /api/v1/agents/
secret field is returned only when a new agent is created. Store it securely — it cannot be retrieved later.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Agent name (must be unique within the organization) |
description | string | No | Human-readable description |
events | array | Yes | Event types to subscribe to (see Event Types) |
callback_url | string | No | HTTPS URL for event delivery (push mode) |
is_active | boolean | No | Whether the agent is enabled (default: true) |
project | string (UUID) | No | Scope the agent to a specific project |
task_types | array | No | Limit to specific task types (default: all) |
Request
curl -X POST "https://api.avala.ai/api/v1/agents/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"]
}'
import requests
response = requests.post(
"https://api.avala.ai/api/v1/agents/",
headers={
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
json={
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"]
}
)
agent = response.json()
const response = await fetch(
"https://api.avala.ai/api/v1/agents/",
{
method: "POST",
headers: {
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "QC Review Agent",
description: "Automatically reviews annotation results for quality",
events: ["result.submitted"],
callback_url: "https://my-agent.example.com/webhook",
project: "770a9600-a40d-63f6-c938-668877660000",
task_types: ["bounding_box", "polygon"],
}),
}
);
const agent = await response.json();
body := strings.NewReader(`{
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"]
}`)
req, _ := http.NewRequest("POST", "https://api.avala.ai/api/v1/agents/", body)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
Response
{
"uid": "b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f",
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"secret": "a7f3b9c1e2d4f6a8b0c2d4e6f8a0b2c4d6e8f0a2",
"is_active": true,
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"],
"created_at": "2025-03-15T10:00:00Z",
"updated_at": "2025-03-15T10:00:00Z"
}
The
secret is only returned once, at creation time. Store it securely. Use it to verify callback signatures from Avala. If you POST with the name of an existing agent, the agent is updated and the secret is not re-returned. To rotate the secret, delete the agent and re-create it.Get Agent
GET /api/v1/agents/{uid}/
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
uid | string (UUID) | Yes | Agent registration UID (path parameter) |
Request
curl "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY"
import requests
response = requests.get(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
)
agent = response.json()
const response = await fetch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
{
headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
}
);
const agent = await response.json();
req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/", nil)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
Response
{
"uid": "b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f",
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"is_active": true,
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"],
"execution_stats": {
"completed": 142,
"pending": 3,
"failed": 1
},
"created_at": "2025-03-15T10:00:00Z",
"updated_at": "2025-03-15T10:00:00Z"
}
Fields
All fields from List Agents plus:| Field | Type | Description |
|---|---|---|
execution_stats | object | Map of execution status to count (e.g., {"completed": 142, "pending": 3}) |
Update Agent
PUT /api/v1/agents/{uid}/
PATCH for partial updates.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
uid | string (UUID) | Yes | Agent registration UID (path parameter) |
name | string | Yes (PUT) | Agent name |
description | string | No | Human-readable description |
events | array | Yes (PUT) | Event types to subscribe to |
callback_url | string | No | HTTPS URL for event delivery |
is_active | boolean | No | Whether the agent is enabled |
project | string (UUID) | No | Project to scope the agent to |
task_types | array | No | Task types to handle |
Request
curl -X PATCH "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"is_active": false
}'
import requests
response = requests.patch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
headers={
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
json={"is_active": False}
)
agent = response.json()
const response = await fetch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
{
method: "PATCH",
headers: {
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ is_active: false }),
}
);
const agent = await response.json();
body := strings.NewReader(`{"is_active": false}`)
req, _ := http.NewRequest("PATCH", "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/", body)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
Response
{
"uid": "b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f",
"name": "QC Review Agent",
"description": "Automatically reviews annotation results for quality",
"events": ["result.submitted"],
"callback_url": "https://my-agent.example.com/webhook",
"is_active": false,
"project": "770a9600-a40d-63f6-c938-668877660000",
"task_types": ["bounding_box", "polygon"],
"created_at": "2025-03-15T10:00:00Z",
"updated_at": "2025-03-15T12:30:00Z"
}
Delete Agent
DELETE /api/v1/agents/{uid}/
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
uid | string (UUID) | Yes | Agent registration UID (path parameter) |
Request
curl -X DELETE "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY"
import requests
response = requests.delete(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
)
const response = await fetch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/",
{
method: "DELETE",
headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
}
);
req, _ := http.NewRequest("DELETE", "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/", nil)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
Response
Returns204 No Content on success.
List Executions
GET /api/v1/agents/{uid}/executions/
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
uid | string (UUID) | Yes | Agent registration UID (path parameter) |
status | string | No | Filter by execution status (query parameter) |
cursor | string | No | Cursor for pagination (query parameter) |
limit | integer | No | Number of results per page (query parameter) |
Request
curl "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/executions/?status=pending" \
-H "X-Avala-Api-Key: $AVALA_API_KEY"
import requests
response = requests.get(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/executions/",
headers={"X-Avala-Api-Key": "YOUR_API_KEY"},
params={"status": "pending"}
)
executions = response.json()["results"]
const response = await fetch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/executions/?status=pending",
{
headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
}
);
const { results } = await response.json();
req, _ := http.NewRequest("GET", "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/executions/?status=pending", nil)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
Response
{
"next": null,
"previous": null,
"results": [
{
"uid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"registration": "b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f",
"event_type": "result.submitted",
"task": "880b0700-d51e-74a7-d049-779988770000",
"result": "990c1800-b62f-85a8-e150-880099881111",
"status": "pending",
"action": null,
"event_payload": {
"event": "result.submitted",
"result_uid": "990c1800-b62f-85a8-e150-880099881111"
},
"response_payload": null,
"error_message": null,
"started_at": "2025-03-15T14:00:00Z",
"completed_at": null,
"created_at": "2025-03-15T14:00:00Z",
"updated_at": "2025-03-15T14:00:00Z"
}
]
}
Execution Fields
| Field | Type | Description |
|---|---|---|
uid | string (UUID) | Unique identifier for the execution |
registration | string (UUID) | UID of the agent registration |
event_type | string | Event that triggered this execution |
task | string (UUID) | null | Associated task UID, if applicable |
result | string (UUID) | null | Associated result UID, if applicable |
status | string | Execution status (see Execution Statuses) |
action | string | null | Action taken by the agent (see Agent Actions) |
event_payload | object | Event data sent to the agent |
response_payload | object | null | Response data from the agent |
error_message | string | null | Error message if the execution failed |
started_at | string (datetime) | null | When execution started |
completed_at | string (datetime) | null | When execution completed |
created_at | string (datetime) | ISO 8601 timestamp of creation |
updated_at | string (datetime) | ISO 8601 timestamp of the last update |
Submit Action
POST /api/v1/agent-actions/
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
execution | string (UUID) | Yes | UID of the execution to respond to |
action | string | Yes | Decision: approve, reject, flag, or skip |
reason | string | No | Human-readable reason for the decision (max 2048 characters) |
metadata | object | No | Additional structured data (max 64 KB) |
Request
curl -X POST "https://api.avala.ai/api/v1/agent-actions/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"execution": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"action": "approve",
"reason": "All annotations meet quality threshold"
}'
import requests
response = requests.post(
"https://api.avala.ai/api/v1/agent-actions/",
headers={
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
json={
"execution": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"action": "approve",
"reason": "All annotations meet quality threshold"
}
)
result = response.json()
const response = await fetch(
"https://api.avala.ai/api/v1/agent-actions/",
{
method: "POST",
headers: {
"X-Avala-Api-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
execution: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
action: "approve",
reason: "All annotations meet quality threshold",
}),
}
);
const result = await response.json();
body := strings.NewReader(`{
"execution": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"action": "approve",
"reason": "All annotations meet quality threshold"
}`)
req, _ := http.NewRequest("POST", "https://api.avala.ai/api/v1/agent-actions/", body)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
Response
{
"detail": "Action recorded.",
"execution_uid": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90",
"action": "approve"
}
Test Agent
POST /api/v1/agents/{uid}/test/
ping event to the agent. If the agent has a callback URL, the event is delivered asynchronously. Use this to verify connectivity.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
uid | string (UUID) | Yes | Agent registration UID (path parameter) |
Request
curl -X POST "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/test/" \
-H "X-Avala-Api-Key: $AVALA_API_KEY"
import requests
response = requests.post(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/test/",
headers={"X-Avala-Api-Key": "YOUR_API_KEY"}
)
result = response.json()
const response = await fetch(
"https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/test/",
{
method: "POST",
headers: { "X-Avala-Api-Key": "YOUR_API_KEY" },
}
);
const result = await response.json();
req, _ := http.NewRequest("POST", "https://api.avala.ai/api/v1/agents/b3a1d7c0-4e2f-4b8a-9c6d-1a2b3c4d5e6f/test/", nil)
req.Header.Set("X-Avala-Api-Key", "YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
Response
{
"detail": "Test event queued.",
"execution_uid": "e5f6a7b8-c9d0-1e2f-3a4b-5c6d7e8f9a01",
"has_callback": true
}
Event Types
| Event | Description |
|---|---|
dataset.created | A new dataset was created |
dataset.updated | An existing dataset was updated |
dataset.deleted | A dataset was deleted |
export.completed | An export job completed successfully |
export.failed | An export job failed |
task.completed | A task was marked as complete |
result.submitted | An annotation result was submitted |
result.accepted | An annotation result was accepted |
result.rejected | An annotation result was rejected |
Execution Statuses
| Status | Description |
|---|---|
pending | Execution created, waiting for agent to process |
running | Agent is currently processing the event |
completed | Agent has submitted an action |
failed | Execution failed (callback error or internal failure) |
timed_out | Agent did not respond within the 10-minute timeout |
Agent Actions
| Action | Description |
|---|---|
approve | Accept the annotation result |
reject | Reject the annotation result |
flag | Flag the result for human review |
skip | Skip this execution without taking action |
Error Responses
Validation Error (400)
{
"events": ["Invalid events: invalid.event"],
"callback_url": ["callback_url must use HTTPS."]
}
Unauthorized (401)
{
"detail": "Invalid API key."
}
X-Avala-Api-Key header is missing or contains an invalid key.
Permission Denied (403)
{
"detail": "You do not have permission to perform this action."
}
Not Found (404)
{
"detail": "Not found."
}