Tools
11 endpoints. Every path below is relative to the API base URL and already includes the /api/v1 prefix — see conventions for authentication, pagination, errors and idempotency.
| Endpoint | ||
|---|---|---|
| GET | /tools | Lists the organization's tools, newest first, filterable by type, publication state and MCP server |
| POST | /tools | Creates a draft tool, validating the outbound HTTP request configuration for request-making types |
| GET | /tools/{tool} | Returns one tool with its parameter schema and provider configuration |
| PUT | /tools/{tool} | Updates a tool draft with PATCH semantics, re-running the HTTP config validator when relevant |
| DELETE | /tools/{tool} | Deletes a tool from the organization |
| POST | /tools/{tool}/duplicate | Copies a tool into a new unpublished draft |
| POST | /tools/{tool}/publish | Freezes the tool draft into a new immutable version that pinned assistants can resolve |
| GET | /tools/{tool}/validate | Runs the publish-time checks against the tool draft without publishing and returns the error list |
| GET | /tools/{tool}/versions | Lists the tool's published versions, newest first |
| GET | /tools/{tool}/versions/{version} | Returns one published tool version including its frozen configuration |
| POST | /tools/{tool}/versions/{version}/restore | Copies an old tool version back onto the draft and publishes it as a new, higher-numbered version |
Endpoints
Lists the organization's tools, newest first, filterable by type, publication state and MCP server
- Requires
tool.read. - Query params: type, published_only, mcp_server_id, limit (default 25, capped at 100).
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
published_only | boolean | — | default false |
limit | integer | — | default 25 |
curl -X GET "$CALLAGENT_API_URL/tools?published_only=false&limit=25" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools?published_only=false&limit=25`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools?published_only=false&limit=25');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/tools?published_only=false&limit=25",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | Paginated set of ToolResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.read |
Example response, generated from the schema:
{
"data": [
{
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"key": "string",
"description": "string",
"type": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"parameters_schema": {},
"config": {},
"messages": {},
"rejection_plan": {},
"server": {},
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "string",
"mcp_server_id": "01JQ0000000000000000000000",
"mcp_tool_name": "Support Line",
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00"
}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{}
],
"path": "string",
"per_page": 25,
"to": 1,
"total": 1
}
}Creates a draft tool, validating the outbound HTTP request configuration for request-making types
- Requires
tool.write. name,descriptionandtypeare all required. For HTTP tool types the same validator that gates publishing runs at create time.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | max 255 chars |
key | string | null | — | max 96 chars. pattern ^[a-zA-Z_][a-zA-Z0-9_]*$ |
description | string | yes | max 2000 chars |
type | api_request · function · transfer_call · handoff · end_call · sms … | yes | §32. The type drives everything downstream: which form fields the builder shows, which validator runs, and whether the Voice Gateway executes the tool in-process, over HTTP, or in an isolated sandbox worker. |
parameters_schema | string[] | null | — | |
config | string[] | null | — | |
messages | string[] | null | — | |
rejection_plan | string[] | null | — | |
server | string[] | null | — | |
is_async | boolean | null | — | |
timeout_seconds | integer | null | — | min 1. max 120 |
requires_confirmation | boolean | null | — | |
risk_level | read · write · destructive · financial · privileged | null | — | |
metadata | string[] | null | — |
curl -X POST "$CALLAGENT_API_URL/tools" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Support Line",
"description": "string",
"type": "api_request",
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "read"
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Support Line",
"description": "string",
"type": "api_request",
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "read"
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Support Line',
'description' => 'string',
'type' => 'api_request',
'is_async' => true,
'timeout_seconds' => 30,
'requires_confirmation' => true,
'risk_level' => 'read',
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/tools",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"name": "Support Line",
"description": "string",
"type": "api_request",
"is_async": True,
"timeout_seconds": 30,
"requires_confirmation": True,
"risk_level": "read"
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
201 | ToolResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.write |
422 | Validation failed, including structural errors reported on config |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"key": "string",
"description": "string",
"type": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"parameters_schema": {},
"config": {},
"messages": {},
"rejection_plan": {},
"server": {},
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "string",
"mcp_server_id": "01JQ0000000000000000000000",
"mcp_tool_name": "Support Line",
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00"
}
}Returns one tool with its parameter schema and provider configuration
- Requires
tool.read.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X GET "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | ToolResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.read |
404 | No such tool in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"key": "string",
"description": "string",
"type": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"parameters_schema": {},
"config": {},
"messages": {},
"rejection_plan": {},
"server": {},
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "string",
"mcp_server_id": "01JQ0000000000000000000000",
"mcp_tool_name": "Support Line",
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00"
}
}Updates a tool draft with PATCH semantics, re-running the HTTP config validator when relevant
- Requires
tool.write. PATCHis accepted on the same path, with the same body.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | — | max 255 chars |
key | string | null | — | max 96 chars. pattern ^[a-zA-Z_][a-zA-Z0-9_]*$ |
description | string | — | max 2000 chars |
type | api_request · function · transfer_call · handoff · end_call · sms … | — | §32. The type drives everything downstream: which form fields the builder shows, which validator runs, and whether the Voice Gateway executes the tool in-process, over HTTP, or in an isolated sandbox worker. |
parameters_schema | string[] | null | — | |
config | string[] | null | — | |
messages | string[] | null | — | |
rejection_plan | string[] | null | — | |
server | string[] | null | — | |
is_async | boolean | null | — | |
timeout_seconds | integer | null | — | min 1. max 120 |
requires_confirmation | boolean | null | — | |
risk_level | read · write · destructive · financial · privileged | null | — | |
metadata | string[] | null | — |
curl -X PUT "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Support Line",
"type": "api_request",
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "read"
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Support Line",
"type": "api_request",
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "read"
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Support Line',
'type' => 'api_request',
'is_async' => true,
'timeout_seconds' => 30,
'requires_confirmation' => true,
'risk_level' => 'read',
]),
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.put(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"name": "Support Line",
"type": "api_request",
"is_async": True,
"timeout_seconds": 30,
"requires_confirmation": True,
"risk_level": "read"
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | ToolResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.write |
404 | No such tool in this organization |
422 | Validation failed, including structural errors on config |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"key": "string",
"description": "string",
"type": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"parameters_schema": {},
"config": {},
"messages": {},
"rejection_plan": {},
"server": {},
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "string",
"mcp_server_id": "01JQ0000000000000000000000",
"mcp_tool_name": "Support Line",
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00"
}
}Deletes a tool from the organization
- Requires
tool.delete. - This response is not
data-wrapped. - Body is a bare {"deleted": true, "id": "..."}. Deleting needs tool.delete, which is a distinct permission from tool.write.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X DELETE "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.delete(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | Bare JSON object, not data-wrapped |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.delete |
404 | No such tool in this organization |
Example response, generated from the schema:
{
"deleted": true,
"id": null
}Copies a tool into a new unpublished draft
- Requires
tool.write+tool.read. - Requires both tool.write (create) and tool.read (view the source). Optional body field
name.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X POST "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/duplicate" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/duplicate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/duplicate');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/duplicate",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
201 | ToolResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.write or tool.read |
404 | No such tool in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"key": "string",
"description": "string",
"type": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"parameters_schema": {},
"config": {},
"messages": {},
"rejection_plan": {},
"server": {},
"is_async": true,
"timeout_seconds": 30,
"requires_confirmation": true,
"risk_level": "string",
"mcp_server_id": "01JQ0000000000000000000000",
"mcp_tool_name": "Support Line",
"metadata": {},
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00"
}
}Freezes the tool draft into a new immutable version that pinned assistants can resolve
- Requires
tool.write. - Publishing a tool never touches an existing assistant version; a pinned assistant keeps resolving its old version. Optional body field
change_summary.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X POST "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/publish" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/publish`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/publish');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/publish",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
201 | ToolVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.write |
404 | No such tool in this organization |
422 | The tool fails publish-time validation |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"tool_id": "01JQ0000000000000000000000",
"version": 1,
"name": "Support Line",
"key": "string",
"type": "string",
"description": "string",
"parameters_schema": {},
"config": {},
"config_hash": "string",
"change_summary": "string",
"published_at": "2026-01-01T12:00:00+00:00"
}
}Runs the publish-time checks against the tool draft without publishing and returns the error list
- Requires
tool.read. - A failing tool still answers 200 with valid:false — it is a report, not an error.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X GET "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/validate" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/validate`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/validate');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/validate",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | data-wrapped object |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.read |
404 | No such tool in this organization |
Example response, generated from the schema:
{
"data": {
"valid": true,
"errors": [
null
]
}
}Lists the tool's published versions, newest first
- Requires
tool.read. - Page size is fixed at 50 and cannot be changed.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
curl -X GET "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/versions" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/versions`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/versions');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/versions",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | Paginated set of ToolVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.read |
404 | No such tool in this organization |
Example response, generated from the schema:
{
"data": [
{
"id": "01JQ0000000000000000000000",
"object": "string",
"tool_id": "01JQ0000000000000000000000",
"version": 1,
"name": "Support Line",
"key": "string",
"type": "string",
"description": "string",
"parameters_schema": {},
"config": {},
"config_hash": "string",
"change_summary": "string",
"published_at": "2026-01-01T12:00:00+00:00"
}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{}
],
"path": "string",
"per_page": 25,
"to": 1,
"total": 1
}
}Returns one published tool version including its frozen configuration
- Requires
tool.read.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
version | string | yes | The version ID |
curl -X GET "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/versions/3" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/versions/3`, {
method: 'GET',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/versions/3');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.get(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/versions/3",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | ToolVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.read |
404 | No such tool, or the version belongs to another tool |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"tool_id": "01JQ0000000000000000000000",
"version": 1,
"name": "Support Line",
"key": "string",
"type": "string",
"description": "string",
"parameters_schema": {},
"config": {},
"config_hash": "string",
"change_summary": "string",
"published_at": "2026-01-01T12:00:00+00:00"
}
}Copies an old tool version back onto the draft and publishes it as a new, higher-numbered version
- Requires
tool.write. - Always republishes; there is no dry-run flag. A republish validation failure escapes uncaught as 500, not 422.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
tool | string | yes | The tool ID |
version | string | yes | The version ID |
curl -X POST "$CALLAGENT_API_URL/tools/01JQ0000000000000000000000/versions/3/restore" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/tools/01JQ0000000000000000000000/versions/3/restore`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
},
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${error.type}: ${error.message}`);
}
const { data } = await response.json();<?php
$handle = curl_init(getenv('CALLAGENT_API_URL') . '/tools/01JQ0000000000000000000000/versions/3/restore');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
'Accept: application/json',
],
]);
$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status >= 400) {
throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}
$data = $body['data'];import os, requests
response = requests.post(
f"{os.environ['CALLAGENT_API_URL']}/tools/01JQ0000000000000000000000/versions/3/restore",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
201 | ToolVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks tool.write |
404 | No such tool, or the version belongs to another tool |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"tool_id": "01JQ0000000000000000000000",
"version": 1,
"name": "Support Line",
"key": "string",
"type": "string",
"description": "string",
"parameters_schema": {},
"config": {},
"config_hash": "string",
"change_summary": "string",
"published_at": "2026-01-01T12:00:00+00:00"
}
}