Assistants
14 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 | /assistants | Lists the organization's assistants, newest first, with optional search, status and published-only filters |
| POST | /assistants | Creates a draft assistant with its tool, knowledge-base and structured-output attachments and returns it |
| GET | /assistants/{assistant} | Returns one assistant with its attached tools and knowledge bases loaded |
| PUT | /assistants/{assistant} | Updates the assistant draft with PATCH semantics and re-syncs its tool and knowledge attachments |
| DELETE | /assistants/{assistant} | Soft-deletes an assistant so phone numbers, campaigns and past calls keep resolving their history |
| POST | /assistants/{assistant}/duplicate | Copies an assistant into a new draft that inherits its tool version pins verbatim |
| GET | /assistants/{assistant}/preview | Returns the exact resolved configuration snapshot the Voice Gateway would receive for this draft |
| POST | /assistants/{assistant}/publish | Freezes the current draft into a new immutable assistant version and puts it on live traffic |
| POST | /assistants/{assistant}/render-prompt | Renders the assistant's system prompt and first message against a supplied variable context |
| POST | /assistants/{assistant}/unpublish | Takes the assistant off live traffic and back to draft without destroying its version history |
| GET | /assistants/{assistant}/validate | Runs the publish-time checks against the draft without publishing and returns the error list |
| GET | /assistants/{assistant}/versions | Lists the assistant's published versions with their tool and knowledge-base references |
| GET | /assistants/{assistant}/versions/{version} | Returns one published assistant version including its full frozen configuration snapshot |
| POST | /assistants/{assistant}/versions/{version}/restore | Copies an old version's snapshot back onto the draft and, by default, republishes it as a new version |
Endpoints
Lists the organization's assistants, newest first, with optional search, status and published-only filters
- Requires
assistant.read. - Query params: search, status, published_only, limit (default 25, hard-capped at 100).
Query parameters
| Name | Type | Required | Notes |
|---|---|---|---|
published_only | boolean | — | default false |
limit | integer | — | default 25 |
curl -X GET "$CALLAGENT_API_URL/assistants?published_only=false&limit=25" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants?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') . '/assistants?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']}/assistants?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 AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.read |
Example response, generated from the schema:
{
"data": [
{
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [],
"knowledge_bases": [],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_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
}
}Creates a draft assistant with its tool, knowledge-base and structured-output attachments and returns it
- Requires
assistant.write. - Always created as a draft (is_published false). A tools[].tool_version_id that belongs to another tool escapes validation and 500s in the service.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | max 255 chars |
description | string | null | — | max 255 chars |
mode | pipeline · realtime | null | — | |
language | string | null | — | max 16 chars |
additional_languages | string[] | null | — | |
first_message | string | null | — | max 5000 chars |
first_message_mode | assistant_speaks_first · assistant_speaks_first_with_model_generated_message · assistant_waits_for_user | null | — | |
system_prompt | string | null | — | max 100000 chars |
template_strictness | lenient · warn · strict | null | — | |
silence_timeout_seconds | integer | null | — | min 1. max 600 |
max_duration_seconds | integer | null | — | min 10. max 3600 |
transcriber | object | — | |
transcriber.provider | string | null | — | max 48 chars |
model | object | — | |
model.provider | string | null | — | max 48 chars |
model.model | string | null | — | max 96 chars |
voice | object | — | |
voice.provider | string | null | — | max 48 chars |
speech_to_speech_model | string[] | null | — | |
start_speaking_plan | string[] | null | — | |
stop_speaking_plan | string[] | null | — | |
artifact_plan | string[] | null | — | |
analysis_plan | string[] | null | — | |
observability_plan | string[] | null | — | |
message_plan | string[] | null | — | |
keypad_input_plan | string[] | null | — | |
recording_consent_plan | string[] | null | — | |
voicemail_detection_plan | string[] | null | — | |
transfer_plan | string[] | null | — | |
compliance_plan | string[] | null | — | |
background_sound | string[] | null | — | |
background_speech_denoising | string[] | null | — | |
server | object | — | |
server.url | string | null | — | uri. max 2048 chars |
hooks | string[] | null | — | |
fallbacks | string[] | null | — | |
end_call_phrases | string[] | null | — | |
idle_messages | string[] | null | — | |
background_messages | string[] | null | — | |
pronunciations | string[] | null | — | |
custom_keywords | string[] | null | — | |
voice_formatting | string[] | null | — | |
variables | object[] | null | — | |
variable_values | string[] | null | — | |
knowledge_only | boolean | null | — | |
knowledge_only_plan | string[] | null | — | |
metadata | string[] | null | — | |
tools | object[] | null | — | Tenancy: exists is scoped by hand because the global Eloquent scope does not apply to the validator's own query. |
tool_ids | string[] | null | — | |
knowledge_base_ids | string[] | null | — | |
structured_output_ids | string[] | null | — |
curl -X POST "$CALLAGENT_API_URL/assistants" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
}),
});
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') . '/assistants');
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',
'mode' => 'pipeline',
'first_message_mode' => 'assistant_speaks_first',
'template_strictness' => 'lenient',
'silence_timeout_seconds' => 30,
'max_duration_seconds' => 30,
'transcriber' => [
'provider' => 'string',
],
]),
]);
$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']}/assistants",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
201 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.write |
422 | Validation failed, or a referenced id is not in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}Returns one assistant with its attached tools and knowledge bases loaded
- Requires
assistant.read.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X GET "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.read |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}Updates the assistant draft with PATCH semantics and re-syncs its tool and knowledge attachments
- Requires
assistant.write. PATCHis accepted on the same path, with the same body.- An absent field is left alone, not blanked. Sending tools / knowledge_base_ids replaces the whole attachment set.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | — | max 255 chars |
description | string | null | — | max 255 chars |
mode | pipeline · realtime | null | — | |
language | string | null | — | max 16 chars |
additional_languages | string[] | null | — | |
first_message | string | null | — | max 5000 chars |
first_message_mode | assistant_speaks_first · assistant_speaks_first_with_model_generated_message · assistant_waits_for_user | null | — | |
system_prompt | string | null | — | max 100000 chars |
template_strictness | lenient · warn · strict | null | — | |
silence_timeout_seconds | integer | null | — | min 1. max 600 |
max_duration_seconds | integer | null | — | min 10. max 3600 |
transcriber | object | — | |
transcriber.provider | string | null | — | max 48 chars |
model | object | — | |
model.provider | string | null | — | max 48 chars |
model.model | string | null | — | max 96 chars |
voice | object | — | |
voice.provider | string | null | — | max 48 chars |
speech_to_speech_model | string[] | null | — | |
start_speaking_plan | string[] | null | — | |
stop_speaking_plan | string[] | null | — | |
artifact_plan | string[] | null | — | |
analysis_plan | string[] | null | — | |
observability_plan | string[] | null | — | |
message_plan | string[] | null | — | |
keypad_input_plan | string[] | null | — | |
recording_consent_plan | string[] | null | — | |
voicemail_detection_plan | string[] | null | — | |
transfer_plan | string[] | null | — | |
compliance_plan | string[] | null | — | |
background_sound | string[] | null | — | |
background_speech_denoising | string[] | null | — | |
server | object | — | |
server.url | string | null | — | uri. max 2048 chars |
hooks | string[] | null | — | |
fallbacks | string[] | null | — | |
end_call_phrases | string[] | null | — | |
idle_messages | string[] | null | — | |
background_messages | string[] | null | — | |
pronunciations | string[] | null | — | |
custom_keywords | string[] | null | — | |
voice_formatting | string[] | null | — | |
variables | object[] | null | — | |
variable_values | string[] | null | — | |
knowledge_only | boolean | null | — | |
knowledge_only_plan | string[] | null | — | |
metadata | string[] | null | — | |
tools | object[] | null | — | Tenancy: exists is scoped by hand because the global Eloquent scope does not apply to the validator's own query. |
tool_ids | string[] | null | — | |
knowledge_base_ids | string[] | null | — | |
structured_output_ids | string[] | null | — |
curl -X PUT "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/01JQ0000000000000000000000`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
}),
});
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') . '/assistants/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',
'mode' => 'pipeline',
'first_message_mode' => 'assistant_speaks_first',
'template_strictness' => 'lenient',
'silence_timeout_seconds' => 30,
'max_duration_seconds' => 30,
'transcriber' => [
'provider' => 'string',
],
]),
]);
$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']}/assistants/01JQ0000000000000000000000",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"name": "Support Line",
"mode": "pipeline",
"first_message_mode": "assistant_speaks_first",
"template_strictness": "lenient",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"transcriber": {
"provider": "string"
}
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.write |
404 | No such assistant in this organization |
422 | Validation failed, or a referenced id is not in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}Soft-deletes an assistant so phone numbers, campaigns and past calls keep resolving their history
- Requires
assistant.delete. - This response is not
data-wrapped. - Body is a bare {"deleted": true, "id": "..."} — not the usual {"data": ...} envelope. The row is soft-deleted, not destroyed.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X DELETE "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 assistant.delete |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"deleted": true,
"id": null
}Copies an assistant into a new draft that inherits its tool version pins verbatim
- Requires
assistant.write. - Optional body field
name; otherwise a unique "copy" name is generated. The copy starts at version 0, unpublished.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X POST "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/duplicate" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.write |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}Returns the exact resolved configuration snapshot the Voice Gateway would receive for this draft
- Requires
assistant.read.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X GET "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/preview" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/01JQ0000000000000000000000/preview`, {
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') . '/assistants/01JQ0000000000000000000000/preview');
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']}/assistants/01JQ0000000000000000000000/preview",
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 assistant.read |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"schema_version": 1,
"assistant": {
"id": null,
"organization_id": "01JQ0000000000000000000000",
"name": "Support Line",
"description": "string",
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"first_message_interruptions_enabled": true,
"system_prompt": "string",
"end_call_message": "string",
"end_call_function_enabled": true,
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string"
},
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"plans": {
"start_speaking": {},
"stop_speaking": {},
"artifact": {},
"analysis": {},
"observability": {},
"message": {},
"keypad_input": {},
"recording_consent": {},
"voicemail_detection": {},
"transfer": {},
"compliance": {},
"background_sound": {},
"background_speech_denoising": {}
},
"conversation": {
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {}
},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"tools": [
{}
],
"mcp_servers": [
{}
],
"knowledge": {
"bases": [],
"knowledge_only": true,
"knowledge_only_plan": {}
},
"structured_outputs": [
{}
],
"credentials": [
{}
],
"metadata": {}
}
}Freezes the current draft into a new immutable assistant version and puts it on live traffic
- Requires
assistant.publish. - Optional body fields
labelandchange_summary. Publishing is a separate permission from editing.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X POST "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/publish" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 | AssistantVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.publish |
404 | No such assistant in this organization |
422 | The draft fails publish-time validation |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"assistant_id": "01JQ0000000000000000000000",
"version": 1,
"label": null,
"change_summary": "string",
"config_hash": "string",
"config": {},
"tool_refs": {},
"knowledge_base_refs": {},
"published_at": "2026-01-01T12:00:00+00:00"
}
}Renders the assistant's system prompt and first message against a supplied variable context
- Requires
assistant.read. - Body accepts
variables,callandcustomerobjects, none required. A malformed template or (under strict mode) an undefined variable throws and surfaces as 500.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X POST "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/render-prompt" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/01JQ0000000000000000000000/render-prompt`, {
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') . '/assistants/01JQ0000000000000000000000/render-prompt');
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']}/assistants/01JQ0000000000000000000000/render-prompt",
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 assistant.read |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"system_prompt": "string",
"first_message": "string",
"missing": {}
}
}Takes the assistant off live traffic and back to draft without destroying its version history
- Requires
assistant.publish.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X POST "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/unpublish" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/01JQ0000000000000000000000/unpublish`, {
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') . '/assistants/01JQ0000000000000000000000/unpublish');
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']}/assistants/01JQ0000000000000000000000/unpublish",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.publish |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}Runs the publish-time checks against the draft without publishing and returns the error list
- Requires
assistant.read. - A failing configuration still answers 200 with valid:false — it is a report, not an error.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X GET "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/validate" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 assistant.read |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": {
"valid": true,
"errors": [
null
]
}
}Lists the assistant's published versions with their tool and knowledge-base references
- Requires
assistant.read. - Page size is fixed at 50 and cannot be changed. The full
configsnapshot is omitted from the listing; only the show route returns it.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
curl -X GET "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/versions" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 AssistantVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.read |
404 | No such assistant in this organization |
Example response, generated from the schema:
{
"data": [
{
"id": "01JQ0000000000000000000000",
"object": "string",
"assistant_id": "01JQ0000000000000000000000",
"version": 1,
"label": null,
"change_summary": "string",
"config_hash": "string",
"config": {},
"tool_refs": {},
"knowledge_base_refs": {},
"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 assistant version including its full frozen configuration snapshot
- Requires
assistant.read.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
version | string | yes | The version ID |
curl -X GET "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/versions/3" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Accept: application/json"const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/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') . '/assistants/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']}/assistants/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 | AssistantVersionResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.read |
404 | No such assistant, or the version belongs to another assistant |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"assistant_id": "01JQ0000000000000000000000",
"version": 1,
"label": null,
"change_summary": "string",
"config_hash": "string",
"config": {},
"tool_refs": {},
"knowledge_base_refs": {},
"published_at": "2026-01-01T12:00:00+00:00"
}
}Copies an old version's snapshot back onto the draft and, by default, republishes it as a new version
- Requires
assistant.publish. - Optional body flag
publishdefaults to true. History is never rewritten: a new higher version is created. A republish validation failure escapes as 500, not 422.
Path parameters
| Name | Type | Required | Notes |
|---|---|---|---|
assistant | string | yes | The assistant ID |
version | string | yes | The version ID |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
publish | boolean | — | default true |
curl -X POST "$CALLAGENT_API_URL/assistants/01JQ0000000000000000000000/versions/3/restore" \
-H "Authorization: Bearer $CALLAGENT_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"publish": true
}'const response = await fetch(`${process.env.CALLAGENT_API_URL}/assistants/01JQ0000000000000000000000/versions/3/restore`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"publish": true
}),
});
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') . '/assistants/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',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'publish' => true,
]),
]);
$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']}/assistants/01JQ0000000000000000000000/versions/3/restore",
headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
json={
"publish": True
},
timeout=30,
)
response.raise_for_status()
data = response.json()["data"]Responses
| Status | Body |
|---|---|
200 | AssistantResource |
Errors
| Status | When it happens |
|---|---|
403 | The key lacks assistant.publish |
404 | No such assistant, or the version belongs to another assistant |
Example response, generated from the schema:
{
"data": {
"id": "01JQ0000000000000000000000",
"object": "string",
"name": "Support Line",
"description": "string",
"status": "string",
"is_published": true,
"version": 1,
"current_version_id": "01JQ0000000000000000000000",
"published_version_id": "01JQ0000000000000000000000",
"has_unpublished_changes": true,
"mode": "string",
"language": "string",
"additional_languages": {},
"first_message": "string",
"first_message_mode": "string",
"system_prompt": "string",
"silence_timeout_seconds": 30,
"max_duration_seconds": 30,
"template_strictness": "string",
"transcriber": {},
"model": {},
"voice": {},
"speech_to_speech_model": {},
"start_speaking_plan": {},
"stop_speaking_plan": {},
"artifact_plan": {},
"analysis_plan": {},
"observability_plan": {},
"message_plan": {},
"keypad_input_plan": {},
"recording_consent_plan": {},
"voicemail_detection_plan": {},
"transfer_plan": {},
"compliance_plan": {},
"background_sound": {},
"background_speech_denoising": {},
"end_call_phrases": {},
"idle_messages": {},
"background_messages": {},
"pronunciations": {},
"custom_keywords": {},
"voice_formatting": {},
"server": {},
"hooks": {},
"fallbacks": {},
"variables": {},
"variable_values": {},
"knowledge_only": true,
"knowledge_only_plan": {},
"metadata": {},
"tools": [
{}
],
"knowledge_bases": [
{}
],
"created_at": "2026-01-01T12:00:00+00:00",
"updated_at": "2026-01-01T12:00:00+00:00",
"last_published_at": "2026-01-01T12:00:00+00:00"
}
}