Browse the docs

API reference

Agents

Create, duplicate and configure voice agents: their language, voice and model, their call flow, their after-call analysis and the webhook they report to.

List agents

GET/v1/agents
Bearer API key

List the agents of the authenticated tenant with pagination, optionally only those of one entity.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Query parameters

pageinteger
minimum 1default 1example 1
limitinteger
from 1 to 100default 50example 50
entityIdstring<uuid>

Return only the items of this entity. Send this or entityExternalId, not both.

example 550e8400-e29b-41d4-a716-446655440000
entityExternalIdstring

Return only the items of the entity with this external id. Send this or entityId, not both.

1 to 255 charactersexample club-42

Responses

Agents listed successfully

dataobject[]required
Show child attributes
idstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000
namestringrequired
example Alice
genderenum<string>required
example FEMALE
AllowedFEMALEMALE
languageenum<string>required
example en
Allowedfrennlptes
entityIdstring<uuid> | nullrequired

The agent's entity, or null when the agent is shared.

example null
pageCountnumberrequired
example 3

Invalid request

successenum<boolean>required
Allowedfalse
errorobjectrequired
Show child attributes
nameenum<string>required
AllowedZodError
issuesobject[]required
Show child attributes
codestringrequired
example invalid_enum_value
pathstring | number[]required
messagestringrequired
example Invalid email

Unauthorized

errorstringrequired

Entity not found

errorstringrequired

Internal server error

errorstringrequired
GET
curl "https://api.callshift.ai/v1/agents?entityExternalId=club-42" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/agents?entityExternalId=club-42", {
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
  },
});
const data = await res.json();
import os
import requests

res = requests.get(
    "https://api.callshift.ai/v1/agents?entityExternalId=club-42",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
)
print(res.json())
Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Alice",
      "gender": "FEMALE",
      "language": "en",
      "entityId": null
    }
  ],
  "pageCount": 3
}
{
  "success": false,
  "error": {
    "name": "ZodError",
    "issues": [
      {
        "code": "invalid_enum_value",
        "path": [
          "contacts",
          0,
          "email"
        ],
        "message": "Invalid email"
      }
    ]
  }
}
{
  "error": "Authentication error"
}
{
  "error": "Entity not found"
}
{
  "error": "Internal server error"
}

Create a new agent

POST/v1/agents
Bearer API key

Create a new agent from scratch for the authenticated tenant.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Body application/json

namestringrequired
1 to 50 charactersexample Alice
genderenum<string>required
example FEMALE
AllowedFEMALEMALE
languageenum<string>required
example en
Allowedfrennlptes
backgroundSoundenum<string> | null

Ambience played under the call, or null for none.

example office_ambience
Allowedoffice_ambiencecity_ambienceforest_ambiencecrowded_roomkeyboard_typingkeyboard_typing2hold_musicgym_ambience
backgroundSoundVolumenumber | null

Volume of the background sound, from 0 to 1. null uses the default of 0.2.

from 0 to 1example 0.2
silenceTimeoutSecondsinteger | null

Seconds of caller silence before the agent hangs up, from 5 to 120. null uses the default of 25.

from 5 to 120example 15
maxDurationSecondsinteger | null

Maximum length of a call, in seconds, from 60 to 3600. The call then ends with endedReason max-duration-exceeded. null uses the default of 420.

from 60 to 3600example 600
providerstring

Model provider: google, openai or xai. Defaults to google on create.

up to 50 charactersexample google
modelstring

Realtime (speech-to-speech) models: gemini-3.8-live, gemini-live-3.1-flash (google), gpt-realtime-2.1-mini, gpt-live-1 (openai), grok-voice-3.0 (xai). Pipeline models: gpt-4o-mini, gpt-4o, gpt-4.1-mini, gpt-5-mini, gpt-5.4-mini (openai). Defaults to gemini-live-3.1-flash on create.

up to 50 charactersexample gemini-live-3.1-flash
voiceIdstring
up to 50 characters
temperaturenumber
from 0 to 2
maxTokensnumber
from 1 to 10000
minEndpointingDelaynumber | null

Minimum time, in seconds, the agent waits after the caller stops speaking before answering, from 0.3 to 2.5. Raise it if callers get cut off mid-sentence (with a slow STT like Azure, try 0.9). Higher values slow every reply. Only applies to pipeline models. null uses the default.

from 0.3 to 2.5example 0.9
summaryPromptstring | null
evaluationPromptstring | null
informationToCollectobject[]
Show child attributes
idstringrequired
namestringrequired
at least 1 character
typeenum<string>required
Allowedstringnumberbooleanenum
descriptionstring
enumValuesstring[]
diagramobject

The conversation flow. knowHow node prompts are HTML. A tool (see GET /v1/tools) is attached to the agent by referencing it in a prompt with a <tool-node> element:

<tool-node functionname="checkOrder" category="custom" toolslug="" toolid="550e8400-e29b-41d4-a716-446655440000">Use checkOrder to look up the caller's order.</tool-node>

  • functionname is the camelCase form of the tool name (Check order → checkOrder). The tool is resolved by this name, so renaming a tool detaches it from the agents that reference it until their prompts are updated.
  • category is custom or query for those types, notifications for sendSms and sendEmail.
  • toolid is the tool id. A diagram whose tool node matches no tool of the account by both toolid and functionname is refused (422).
  • The element's text is the instruction the agent reads.

Transferring the call, handing over to another agent and ending the call are nodes (forwardCall, forwardAgent, endCall), not tools.

A forwardCall node with destinationType: "lookup" has no forwardingPhoneNumber: during the call, its lookupUrl receives the same request as a custom tool (with the arguments lookupParameters describes) and answers { "number": "+33…", "message"?, "context"? } or { "error": "…", "context"? } within 5 seconds. The number must be in the country of the line the call is on. The node becomes a tool named after the camelCase of its title, which no other tool of the agent may share (422). Agents on the current voice engine only: the others leave the node out.

Show child attributes
nodesobject[]required
Show the variants
idstringrequired
typeenum<string>required
AllowedstartCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
briefstringrequired
welcomeMessagestringrequired
outboundobject
Show child attributes
voiceMailEnabledboolean
voiceMailMessagestringrequired
voiceMailExpectedDurationnumber
from 5 to 60
voiceMailProviderenum<string>
Allowedgoogleopenai
welcomeMessagestringrequired
firstMessageModeenum<string>
Allowedassistant-speaks-firstassistant-waits-for-userassistant-speaks-first-with-model-generated-message
pauseBeforeSpeakingSecondsnumber
from 0 to 5
idstringrequired
typeenum<string>required
AllowedendCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
endCallMessagestringrequired
idstringrequired
typeenum<string>required
AllowedknowHow
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
titlestringrequired
promptstringrequired
idstringrequired
typeenum<string>required
AllowedforwardAgent
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
agentIdstringrequired
at least 1 character
messagestringrequired
descriptionstringrequired
idstringrequired
typeenum<string>required
AllowedforwardCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show the variants
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedcold
greetingMessagestring
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedwarm
greetingMessagestringrequired
at least 1 character
edgesobject[]required
Show child attributes
idstringrequired
sourcestringrequired
targetstringrequired
dataobject
Show child attributes
conditionenum<string>required
AllowedisExistingContactnotExistingContactnotNewCallerisNewCallerinboundOnlyoutboundOnly
entityIdstring<uuid> | null

The entity the item belongs to, or null to make it shared. Send this or entityExternalId, not both.

example 550e8400-e29b-41d4-a716-446655440000
entityExternalIdstring | null

Your external id of the entity the item belongs to, or null to make it shared. Send this or entityId, not both.

1 to 255 charactersexample club-42

Responses

Agent created successfully

idstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Invalid request payload

successenum<boolean>required
Allowedfalse
errorobjectrequired
Show child attributes
nameenum<string>required
AllowedZodError
issuesobject[]required
Show child attributes
codestringrequired
example invalid_enum_value
pathstring | number[]required
messagestringrequired
example Invalid email

Unauthorized

errorstringrequired

Entity not found

errorstringrequired

The diagram references a tool that does not exist, or names a looked-up forwardCall node like another tool

errorstringrequired

Internal server error

errorstringrequired
POST
curl -X POST "https://api.callshift.ai/v1/agents" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alice",
    "gender": "FEMALE",
    "language": "en",
    "provider": "google",
    "model": "gemini-live-3.1-flash",
    "silenceTimeoutSeconds": 15,
    "maxDurationSeconds": 600
  }'
const res = await fetch("https://api.callshift.ai/v1/agents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "Alice",
    "gender": "FEMALE",
    "language": "en",
    "provider": "google",
    "model": "gemini-live-3.1-flash",
    "silenceTimeoutSeconds": 15,
    "maxDurationSeconds": 600
  }),
});
const data = await res.json();
import os
import requests

res = requests.post(
    "https://api.callshift.ai/v1/agents",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "name": "Alice",
        "gender": "FEMALE",
        "language": "en",
        "provider": "google",
        "model": "gemini-live-3.1-flash",
        "silenceTimeoutSeconds": 15,
        "maxDurationSeconds": 600,
    },
)
print(res.json())
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000"
}
{
  "success": false,
  "error": {
    "name": "ZodError",
    "issues": [
      {
        "code": "invalid_enum_value",
        "path": [
          "contacts",
          0,
          "email"
        ],
        "message": "Invalid email"
      }
    ]
  }
}
{
  "error": "Authentication error"
}
{
  "error": "Entity not found"
}
{
  "error": "The diagram references a tool that does not exist, or names a looked-up forwardCall node like another tool"
}
{
  "error": "Internal server error"
}

Get agent details

GET/v1/agents/{agentId}
Bearer API key

Retrieve detailed information about a specific agent by ID.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Path parameters

agentIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Responses

Agent details retrieved successfully

idstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000
namestringrequired
example Alice
genderenum<string>required
example FEMALE
AllowedFEMALEMALE
languageenum<string>required
example en
Allowedfrennlptes
entityIdstring<uuid> | nullrequired

The agent's entity, or null when the agent is shared.

example null
backgroundSoundenum<string> | nullrequired
example office_ambience
Allowedoffice_ambiencecity_ambienceforest_ambiencecrowded_roomkeyboard_typingkeyboard_typing2hold_musicgym_ambience
backgroundSoundVolumenumber | nullrequired
example null
silenceTimeoutSecondsinteger | nullrequired
example null
maxDurationSecondsinteger | nullrequired
example null
providerstringrequired
example google
modelstringrequired
example gemini-live-3.1-flash
temperaturenumberrequired
example 1
maxTokensnumberrequired
example 1500
minEndpointingDelaynumber | nullrequired
example null
summaryPromptstring | nullrequired
example null
evaluationPromptstring | nullrequired
example null
informationToCollectobject[] | nullrequired
Show child attributes
idstringrequired
namestringrequired
at least 1 character
typeenum<string>required
Allowedstringnumberbooleanenum
descriptionstring
enumValuesstring[]
diagramobjectrequired

The conversation flow. knowHow node prompts are HTML. A tool (see GET /v1/tools) is attached to the agent by referencing it in a prompt with a <tool-node> element:

<tool-node functionname="checkOrder" category="custom" toolslug="" toolid="550e8400-e29b-41d4-a716-446655440000">Use checkOrder to look up the caller's order.</tool-node>

  • functionname is the camelCase form of the tool name (Check order → checkOrder). The tool is resolved by this name, so renaming a tool detaches it from the agents that reference it until their prompts are updated.
  • category is custom or query for those types, notifications for sendSms and sendEmail.
  • toolid is the tool id. A diagram whose tool node matches no tool of the account by both toolid and functionname is refused (422).
  • The element's text is the instruction the agent reads.

Transferring the call, handing over to another agent and ending the call are nodes (forwardCall, forwardAgent, endCall), not tools.

A forwardCall node with destinationType: "lookup" has no forwardingPhoneNumber: during the call, its lookupUrl receives the same request as a custom tool (with the arguments lookupParameters describes) and answers { "number": "+33…", "message"?, "context"? } or { "error": "…", "context"? } within 5 seconds. The number must be in the country of the line the call is on. The node becomes a tool named after the camelCase of its title, which no other tool of the agent may share (422). Agents on the current voice engine only: the others leave the node out.

Show child attributes
nodesobject[]required
Show the variants
idstringrequired
typeenum<string>required
AllowedstartCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
briefstringrequired
welcomeMessagestringrequired
outboundobject
Show child attributes
voiceMailEnabledboolean
voiceMailMessagestringrequired
voiceMailExpectedDurationnumber
from 5 to 60
voiceMailProviderenum<string>
Allowedgoogleopenai
welcomeMessagestringrequired
firstMessageModeenum<string>
Allowedassistant-speaks-firstassistant-waits-for-userassistant-speaks-first-with-model-generated-message
pauseBeforeSpeakingSecondsnumber
from 0 to 5
idstringrequired
typeenum<string>required
AllowedendCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
endCallMessagestringrequired
idstringrequired
typeenum<string>required
AllowedknowHow
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
titlestringrequired
promptstringrequired
idstringrequired
typeenum<string>required
AllowedforwardAgent
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
agentIdstringrequired
at least 1 character
messagestringrequired
descriptionstringrequired
idstringrequired
typeenum<string>required
AllowedforwardCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show the variants
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedcold
greetingMessagestring
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedwarm
greetingMessagestringrequired
at least 1 character
edgesobject[]required
Show child attributes
idstringrequired
sourcestringrequired
targetstringrequired
dataobject
Show child attributes
conditionenum<string>required
AllowedisExistingContactnotExistingContactnotNewCallerisNewCallerinboundOnlyoutboundOnly
webhookobject | nullrequired

After-call automation webhook settings, or null when never configured.

Show child attributes
enabledbooleanrequired
example true
webhookIdstring<uuid>
example 550e8400-e29b-41d4-a716-446655440000
toolsobject[]required

Tools referenced by the agent's diagram prompts (read-only: attach or detach a tool through diagram).

Show child attributes
idstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000
typeenum<string>required
AllowedcustomquerysendSmssendEmail
namestringrequired
example Check order

Unauthorized

errorstringrequired

Agent not found

errorstringrequired

Internal server error

errorstringrequired
GET
curl "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000", {
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
  },
});
const data = await res.json();
import os
import requests

res = requests.get(
    "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
)
print(res.json())
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Alice",
  "gender": "FEMALE",
  "language": "en",
  "entityId": null,
  "backgroundSound": "office_ambience",
  "backgroundSoundVolume": null,
  "silenceTimeoutSeconds": null,
  "maxDurationSeconds": null,
  "provider": "google",
  "model": "gemini-live-3.1-flash",
  "temperature": 1,
  "maxTokens": 1500,
  "minEndpointingDelay": null,
  "summaryPrompt": null,
  "evaluationPrompt": null,
  "informationToCollect": [
    {
      "id": "visit",
      "name": "Visit booked",
      "type": "boolean",
      "description": "Did the caller book a visit?"
    },
    {
      "id": "day",
      "name": "Preferred day",
      "type": "enum",
      "enumValues": [
        "Weekday",
        "Weekend"
      ]
    }
  ],
  "diagram": {
    "nodes": [
      {
        "id": "start",
        "type": "startCall",
        "position": {
          "x": 0,
          "y": 0
        },
        "data": {
          "brief": "<p>You are Alice, the receptionist of Club Lyon Part-Dieu.</p>",
          "welcomeMessage": "Hello, this is Alice, the AI assistant of Club Lyon Part-Dieu. How can I help?"
        }
      },
      {
        "id": "hours",
        "type": "knowHow",
        "position": {
          "x": 0,
          "y": 160
        },
        "data": {
          "title": "Opening hours",
          "prompt": "<p>The club is open every day from 6am to 11pm.</p>"
        }
      },
      {
        "id": "end",
        "type": "endCall",
        "position": {
          "x": 0,
          "y": 320
        },
        "data": {
          "endCallMessage": "Thank you for calling. Have a good day!"
        }
      }
    ],
    "edges": [
      {
        "id": "e1",
        "source": "start",
        "target": "hours"
      },
      {
        "id": "e2",
        "source": "hours",
        "target": "end"
      }
    ]
  },
  "webhook": {
    "enabled": true,
    "webhookId": "550e8400-e29b-41d4-a716-446655440000"
  },
  "tools": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "type": "custom",
      "name": "Check order"
    }
  ]
}
{
  "error": "Authentication error"
}
{
  "error": "Agent not found"
}
{
  "error": "Internal server error"
}

Partially update an agent's settings

PATCH/v1/agents/{agentId}
Bearer API key

Apply updates to the agent's fields, such as name, language, model, temperature, summary/evaluation prompts, information to collect, and diagram.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Path parameters

agentIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Body application/json

namestring
1 to 50 characters
genderenum<string>
AllowedFEMALEMALE
languageenum<string>
example en
Allowedfrennlptes
backgroundSoundenum<string> | null

Ambience played under the call, or null for none.

example office_ambience
Allowedoffice_ambiencecity_ambienceforest_ambiencecrowded_roomkeyboard_typingkeyboard_typing2hold_musicgym_ambience
backgroundSoundVolumenumber | null

Volume of the background sound, from 0 to 1. null uses the default of 0.2.

from 0 to 1example 0.2
silenceTimeoutSecondsinteger | null

Seconds of caller silence before the agent hangs up, from 5 to 120. null uses the default of 25.

from 5 to 120example 15
maxDurationSecondsinteger | null

Maximum length of a call, in seconds, from 60 to 3600. The call then ends with endedReason max-duration-exceeded. null uses the default of 420.

from 60 to 3600example 600
providerstring

Model provider: google, openai or xai. Defaults to google on create.

up to 50 charactersexample google
modelstring

Realtime (speech-to-speech) models: gemini-3.8-live, gemini-live-3.1-flash (google), gpt-realtime-2.1-mini, gpt-live-1 (openai), grok-voice-3.0 (xai). Pipeline models: gpt-4o-mini, gpt-4o, gpt-4.1-mini, gpt-5-mini, gpt-5.4-mini (openai). Defaults to gemini-live-3.1-flash on create.

up to 50 charactersexample gemini-live-3.1-flash
voiceIdstring
up to 50 characters
temperaturenumber
from 0 to 2
maxTokensnumber
from 1 to 10000
minEndpointingDelaynumber | null

Minimum time, in seconds, the agent waits after the caller stops speaking before answering, from 0.3 to 2.5. Raise it if callers get cut off mid-sentence (with a slow STT like Azure, try 0.9). Higher values slow every reply. Only applies to pipeline models. null uses the default.

from 0.3 to 2.5example 0.9
summaryPromptstring | null
evaluationPromptstring | null
informationToCollectobject[]
Show child attributes
idstringrequired
namestringrequired
at least 1 character
typeenum<string>required
Allowedstringnumberbooleanenum
descriptionstring
enumValuesstring[]
diagramobject

The conversation flow. knowHow node prompts are HTML. A tool (see GET /v1/tools) is attached to the agent by referencing it in a prompt with a <tool-node> element:

<tool-node functionname="checkOrder" category="custom" toolslug="" toolid="550e8400-e29b-41d4-a716-446655440000">Use checkOrder to look up the caller's order.</tool-node>

  • functionname is the camelCase form of the tool name (Check order → checkOrder). The tool is resolved by this name, so renaming a tool detaches it from the agents that reference it until their prompts are updated.
  • category is custom or query for those types, notifications for sendSms and sendEmail.
  • toolid is the tool id. A diagram whose tool node matches no tool of the account by both toolid and functionname is refused (422).
  • The element's text is the instruction the agent reads.

Transferring the call, handing over to another agent and ending the call are nodes (forwardCall, forwardAgent, endCall), not tools.

A forwardCall node with destinationType: "lookup" has no forwardingPhoneNumber: during the call, its lookupUrl receives the same request as a custom tool (with the arguments lookupParameters describes) and answers { "number": "+33…", "message"?, "context"? } or { "error": "…", "context"? } within 5 seconds. The number must be in the country of the line the call is on. The node becomes a tool named after the camelCase of its title, which no other tool of the agent may share (422). Agents on the current voice engine only: the others leave the node out.

Show child attributes
nodesobject[]required
Show the variants
idstringrequired
typeenum<string>required
AllowedstartCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
briefstringrequired
welcomeMessagestringrequired
outboundobject
Show child attributes
voiceMailEnabledboolean
voiceMailMessagestringrequired
voiceMailExpectedDurationnumber
from 5 to 60
voiceMailProviderenum<string>
Allowedgoogleopenai
welcomeMessagestringrequired
firstMessageModeenum<string>
Allowedassistant-speaks-firstassistant-waits-for-userassistant-speaks-first-with-model-generated-message
pauseBeforeSpeakingSecondsnumber
from 0 to 5
idstringrequired
typeenum<string>required
AllowedendCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
endCallMessagestringrequired
idstringrequired
typeenum<string>required
AllowedknowHow
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
titlestringrequired
promptstringrequired
idstringrequired
typeenum<string>required
AllowedforwardAgent
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show child attributes
agentIdstringrequired
at least 1 character
messagestringrequired
descriptionstringrequired
idstringrequired
typeenum<string>required
AllowedforwardCall
positionobjectrequired
Show child attributes
xnumberrequired
ynumberrequired
dataobjectrequired
Show the variants
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedcold
greetingMessagestring
titlestringrequired
at least 1 character
promptstringrequired
at least 1 character
forwardingMessagestringrequired
at least 1 character
destinationTypeenum<string>
default "fixed"
Allowedfixedlookup
forwardingPhoneNumberstring
lookupUrlstring
lookupMessagestring
lookupParametersobject
Show child attributes
typeenum<string>required
Allowedobject
propertiesobjectrequired
requiredstring[]
holdMusicenum<string>
default "default"
Alloweddefaultcalmcustom
holdMusicUrlstring<uri> | enum<string>
humanDetectionEnabledboolean
default false
humanDetectionTimeoutnumber
from 10 to 120default 30
whisperMessagestring
threeWayIntroductionstring
transferTimeoutnumber
from 30 to 300default 60
fallbackMessagestring
transferModeenum<string>required
Allowedwarm
greetingMessagestringrequired
at least 1 character
edgesobject[]required
Show child attributes
idstringrequired
sourcestringrequired
targetstringrequired
dataobject
Show child attributes
conditionenum<string>required
AllowedisExistingContactnotExistingContactnotNewCallerisNewCallerinboundOnlyoutboundOnly
entityIdstring<uuid> | null

The entity the item belongs to, or null to make it shared. Send this or entityExternalId, not both.

example 550e8400-e29b-41d4-a716-446655440000
entityExternalIdstring | null

Your external id of the entity the item belongs to, or null to make it shared. Send this or entityId, not both.

1 to 255 charactersexample club-42

Responses

Agent updated successfully.

successenum<boolean>required
Allowedtrue

Invalid request parameters or payload

successenum<boolean>required
Allowedfalse
errorobjectrequired
Show child attributes
nameenum<string>required
AllowedZodError
issuesobject[]required
Show child attributes
codestringrequired
example invalid_enum_value
pathstring | number[]required
messagestringrequired
example Invalid email

Unauthorized

errorstringrequired

Agent or entity not found

errorstringrequired

The change would link items of two different entities. The error names them.

errorstringrequired

The diagram references a tool that does not exist, or names a looked-up forwardCall node like another tool

errorstringrequired

Internal server error

errorstringrequired
PATCH
curl -X PATCH "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Alice",
    "temperature": 0.7,
    "maxDurationSeconds": 600
  }'
const res = await fetch("https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "Alice",
    "temperature": 0.7,
    "maxDurationSeconds": 600
  }),
});
const data = await res.json();
import os
import requests

res = requests.patch(
    "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "name": "Alice",
        "temperature": 0.7,
        "maxDurationSeconds": 600,
    },
)
print(res.json())
Response
{
  "success": true
}
{
  "success": false,
  "error": {
    "name": "ZodError",
    "issues": [
      {
        "code": "invalid_enum_value",
        "path": [
          "contacts",
          0,
          "email"
        ],
        "message": "Invalid email"
      }
    ]
  }
}
{
  "error": "Authentication error"
}
{
  "error": "Agent or entity not found"
}
{
  "error": "The change would link items of two different entities. The error names them"
}
{
  "error": "The diagram references a tool that does not exist, or names a looked-up forwardCall node like another tool"
}
{
  "error": "Internal server error"
}

Delete an agent

DELETE/v1/agents/{agentId}
Bearer API key

Soft-delete an agent by ID and release its assigned phone numbers.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Path parameters

agentIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Responses

Agent deleted successfully

No content.

Unauthorized

errorstringrequired

Agent not found

errorstringrequired

Internal server error

errorstringrequired
DELETE
curl -X DELETE "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
  },
});
console.log(res.status); // 204
import os
import requests

res = requests.delete(
    "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
)
print(res.status_code)  # 204
Response
No content
{
  "error": "Authentication error"
}
{
  "error": "Agent not found"
}
{
  "error": "Internal server error"
}

Duplicate agent

POST/v1/agents/{agentId}/duplicate
Bearer API key

Duplicate an existing agent for the authenticated tenant. The copy stays in the source agent's entity unless the body names another one, or null for shared. A copy into another entity is refused while the source sends its after-call data to a webhook of its entity.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Path parameters

agentIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Body application/json

Omit both fields to keep the copy in the source agent's entity.

entityIdstring<uuid> | null

The entity the item belongs to, or null to make it shared. Send this or entityExternalId, not both.

example 550e8400-e29b-41d4-a716-446655440000
entityExternalIdstring | null

Your external id of the entity the item belongs to, or null to make it shared. Send this or entityId, not both.

1 to 255 charactersexample club-42

Responses

Agent duplicated successfully

idstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Invalid request payload

successenum<boolean>required
Allowedfalse
errorobjectrequired
Show child attributes
nameenum<string>required
AllowedZodError
issuesobject[]required
Show child attributes
codestringrequired
example invalid_enum_value
pathstring | number[]required
messagestringrequired
example Invalid email

Unauthorized

errorstringrequired

Agent or entity not found

errorstringrequired

The change would link items of two different entities. The error names them.

errorstringrequired

Internal server error

errorstringrequired
POST
curl -X POST "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/duplicate" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "entityExternalId": "club-42"
  }'
const res = await fetch("https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/duplicate", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "entityExternalId": "club-42"
  }),
});
const data = await res.json();
import os
import requests

res = requests.post(
    "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/duplicate",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "entityExternalId": "club-42",
    },
)
print(res.json())
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000"
}
{
  "success": false,
  "error": {
    "name": "ZodError",
    "issues": [
      {
        "code": "invalid_enum_value",
        "path": [
          "contacts",
          0,
          "email"
        ],
        "message": "Invalid email"
      }
    ]
  }
}
{
  "error": "Authentication error"
}
{
  "error": "Agent or entity not found"
}
{
  "error": "The change would link items of two different entities. The error names them"
}
{
  "error": "Internal server error"
}

Assign an after-call webhook to an agent

PUT/v1/agents/{agentId}/webhook
Bearer API key

Enable the agent's after-call automation webhook and point it at one of the tenant's webhooks, or disable it. A webhook of another entity than the agent's is refused. Other notification settings (SMS, Slack) are left untouched.

Authorization

Authorizationstringrequired

Bearer <API key>, a key created at app.callshift.ai/api-keys.

Path parameters

agentIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000

Body application/json

enabledenum<boolean>required
Allowedtrue
webhookIdstring<uuid>required
example 550e8400-e29b-41d4-a716-446655440000
enabledenum<boolean>required
Allowedfalse

Responses

Agent webhook settings updated successfully

webhookobject | nullrequired

After-call automation webhook settings, or null when never configured.

Show child attributes
enabledbooleanrequired
example true
webhookIdstring<uuid>
example 550e8400-e29b-41d4-a716-446655440000

Invalid request body

successenum<boolean>required
Allowedfalse
errorobjectrequired
Show child attributes
nameenum<string>required
AllowedZodError
issuesobject[]required
Show child attributes
codestringrequired
example invalid_enum_value
pathstring | number[]required
messagestringrequired
example Invalid email

Unauthorized

errorstringrequired

Agent or webhook not found

errorstringrequired

The change would link items of two different entities. The error names them.

errorstringrequired

Internal server error

errorstringrequired
PUT
curl -X PUT "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/webhook" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "webhookId": "550e8400-e29b-41d4-a716-446655440000"
  }'
const res = await fetch("https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/webhook", {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "enabled": true,
    "webhookId": "550e8400-e29b-41d4-a716-446655440000"
  }),
});
const data = await res.json();
import os
import requests

res = requests.put(
    "https://api.callshift.ai/v1/agents/550e8400-e29b-41d4-a716-446655440000/webhook",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "enabled": True,
        "webhookId": "550e8400-e29b-41d4-a716-446655440000",
    },
)
print(res.json())
Response
{
  "webhook": {
    "enabled": true,
    "webhookId": "550e8400-e29b-41d4-a716-446655440000"
  }
}
{
  "success": false,
  "error": {
    "name": "ZodError",
    "issues": [
      {
        "code": "invalid_enum_value",
        "path": [
          "contacts",
          0,
          "email"
        ],
        "message": "Invalid email"
      }
    ]
  }
}
{
  "error": "Authentication error"
}
{
  "error": "Agent or webhook not found"
}
{
  "error": "The change would link items of two different entities. The error names them"
}
{
  "error": "Internal server error"
}