Browse the docs

API reference

Phone numbers

The account's numbers, SIP, Twilio or Telnyx: list them, choose the agent that answers each one, and register or delete SIP numbers.

List phone numbers

GET/v1/phones
Bearer API key

List every phone number of the authenticated tenant, whatever the way it reached the account: a connected SIP trunk, or a number imported from a vendor such as Twilio or Telnyx. Use GET /phones/sip to list only the SIP ones. Filter on an entity to get only its numbers.

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

Phones listed successfully

dataobject[]required
Show child attributes
idstring<uuid>required
example 0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e
phoneNumberstringrequired
example +15550001234
providerenum<string>required

How the number reached the account: a connected SIP trunk, or an import from the vendor.

example twilio
Allowedsiptwiliotelnyx
isOutboundAllowedbooleanrequired
example true
agentobject | nullrequired
Show child attributes
idstring<uuid>required
namestringrequired
entityIdstring<uuid> | nullrequired

The number's entity, or null when the number 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/phones" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/phones", {
  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/phones",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
)
print(res.json())
Response
{
  "data": [
    {
      "id": "0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e",
      "phoneNumber": "+15550001234",
      "provider": "twilio",
      "isOutboundAllowed": true,
      "agent": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Alice"
      },
      "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"
}

Update a phone number

PATCH/v1/phones/{phoneId}
Bearer API key

Set (or clear, with null) the agent that answers inbound calls on this number, and the entity it belongs to, whatever its provider: SIP, Twilio or Telnyx. Use GET /phones to find the phone id.

Authorization

Authorizationstringrequired

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

Path parameters

phoneIdstring<uuid>required
example 0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e

Body application/json

agentIdstring<uuid> | null

Agent answering inbound calls on this number; null unassigns it.

example 550e8400-e29b-41d4-a716-446655440000
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

Phone updated successfully

successbooleanrequired

Invalid payload, or agent not found in this account

errorstringrequired

Unauthorized

errorstringrequired

Phone or entity not found

errorstringrequired

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

errorstringrequired

Internal server error

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

res = requests.patch(
    "https://api.callshift.ai/v1/phones/550e8400-e29b-41d4-a716-446655440000",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "agentId": "550e8400-e29b-41d4-a716-446655440000",
    },
)
print(res.json())
Response
{
  "success": true
}
{
  "error": "Invalid payload, or agent not found in this account"
}
{
  "error": "Authentication error"
}
{
  "error": "Phone or entity not found"
}
{
  "error": "The change would link items of two different entities. The error names them"
}
{
  "error": "Internal server error"
}

Update a SIP phone number

PATCH/v1/phones/sip/{phoneId}
Bearer API keyAlias of Update a phone number

Same as PATCH /v1/phones/{phoneId}, which works for every provider. Calls-per-second is a property of the SIP trunk, see GET /v1/trunks.

Authorization

Authorizationstringrequired

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

Path parameters

phoneIdstring<uuid>required
example 0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e

Body application/json

agentIdstring<uuid> | null

Agent answering inbound calls on this number; null unassigns it.

example 550e8400-e29b-41d4-a716-446655440000
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

Phone updated successfully

successbooleanrequired

Invalid payload, or agent not found in this account

errorstringrequired

Unauthorized

errorstringrequired

Phone or entity not found

errorstringrequired

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

errorstringrequired

Internal server error

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

res = requests.patch(
    "https://api.callshift.ai/v1/phones/sip/550e8400-e29b-41d4-a716-446655440000",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "agentId": "550e8400-e29b-41d4-a716-446655440000",
    },
)
print(res.json())
Response
{
  "success": true
}
{
  "error": "Invalid payload, or agent not found in this account"
}
{
  "error": "Authentication error"
}
{
  "error": "Phone or entity not found"
}
{
  "error": "The change would link items of two different entities. The error names them"
}
{
  "error": "Internal server error"
}

Delete a SIP phone number

DELETE/v1/phones/sip/{phoneId}
Bearer API key

Delete a SIP phone number and detach it from its outbound SIP trunk.

Authorization

Authorizationstringrequired

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

Path parameters

phoneIdstring<uuid>required
example 0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e

Responses

SIP phone deleted successfully

No content.

Unauthorized

errorstringrequired

Phone not found

errorstringrequired

Internal server error

errorstringrequired
DELETE
curl -X DELETE "https://api.callshift.ai/v1/phones/sip/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/phones/sip/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/phones/sip/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": "Phone not found"
}
{
  "error": "Internal server error"
}

List SIP phone numbers

GET/v1/phones/sip
Bearer API key

List all SIP phone numbers for the authenticated tenant, 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

SIP phones listed successfully

dataobject[]required
Show child attributes
idstring<uuid>required
example 0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e
phoneNumberstringrequired
example +15550001234
agentobject | nullrequired
Show child attributes
idstring<uuid>required
namestringrequired
entityIdstring<uuid> | nullrequired

The number's entity, or null when the number 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/phones/sip" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY"
const res = await fetch("https://api.callshift.ai/v1/phones/sip", {
  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/phones/sip",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
)
print(res.json())
Response
{
  "data": [
    {
      "id": "0d3a7e6b-2b8e-4c5b-9c4e-5f4b9d2a1c8e",
      "phoneNumber": "+15550001234",
      "agent": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Alice"
      },
      "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 SIP phone number

POST/v1/phones/sip
Bearer API key

Connect a SIP trunk and register the phone number for the authenticated tenant.

Authorization

Authorizationstringrequired

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

Body application/json

phoneNumberstringrequired
at least 1 characterexample +15550001234
agentIdstring<uuid> | null
sipTrunkIdstring<uuid>

Attach the number to an existing SIP trunk. When set, the trunk definition fields are ignored.

namestring

Name for a newly created trunk. Defaults to the termination URI.

1 to 100 charactersexample acme-sip
terminationUristring
1 to 100 charactersexample sip.example.com
transportenum<number>

SIP transport: 1=UDP, 2=TCP, 3=TLS

example 1
Allowed123
sipUsernamestring | null
sipPasswordstring | null
requireInboundAuthboolean

Generate credentials the carrier must send on inbound calls. Defaults to false; ignored when sipTrunkId is set.

example false
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

SIP phone created successfully

idstring<uuid>required

Invalid agent

errorstringrequired

Unauthorized

errorstringrequired

SIP trunk or entity not found

errorstringrequired

Phone number already exists, or the agent belongs to another entity

errorstringrequired

Internal server error

errorstringrequired
POST
curl -X POST "https://api.callshift.ai/v1/phones/sip" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phoneNumber": "+33187654321",
    "name": "acme-sip",
    "terminationUri": "sip.example.com",
    "transport": 1,
    "sipUsername": "acme",
    "sipPassword": "your-sip-password",
    "agentId": "550e8400-e29b-41d4-a716-446655440000"
  }'
const res = await fetch("https://api.callshift.ai/v1/phones/sip", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "phoneNumber": "+33187654321",
    "name": "acme-sip",
    "terminationUri": "sip.example.com",
    "transport": 1,
    "sipUsername": "acme",
    "sipPassword": "your-sip-password",
    "agentId": "550e8400-e29b-41d4-a716-446655440000"
  }),
});
const data = await res.json();
import os
import requests

res = requests.post(
    "https://api.callshift.ai/v1/phones/sip",
    headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
    json={
        "phoneNumber": "+33187654321",
        "name": "acme-sip",
        "terminationUri": "sip.example.com",
        "transport": 1,
        "sipUsername": "acme",
        "sipPassword": "your-sip-password",
        "agentId": "550e8400-e29b-41d4-a716-446655440000",
    },
)
print(res.json())
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000"
}
{
  "error": "Invalid agent"
}
{
  "error": "Authentication error"
}
{
  "error": "SIP trunk or entity not found"
}
{
  "error": "Phone number already exists, or the agent belongs to another entity"
}
{
  "error": "Internal server error"
}