API reference
Contacts
Contacts of the CRM, matched by phone number. Update one, or mark a number as opted out so that it is never dialed again.
Update a contact
/v1/contact/{contactId}Update contact properties by contact ID.
Authorization
AuthorizationstringrequiredBearer <API key>, a key created at app.callshift.ai/api-keys.
Path parameters
contactIdstring<uuid>requiredBody application/json
phoneNumberstringsalutationenum<string>mrmrsmsmissfirstNamestringlastNamestringemailstring<email>informationstringmetadataobjectFree-form JSON metadata (advanced mode). When set, replaces the entire metadata blob — takes precedence over information. Injected into the agent prompt via the contact.metadata variable and included in the call-ended webhook payload.
optedOutbooleanResponses
Contact updated successfully
successbooleanrequiredInvalid request parameters or body
successenum<boolean>requiredfalseerrorobjectrequiredShow child attributes
nameenum<string>requiredZodErrorissuesobject[]requiredShow child attributes
codestringrequiredpathstring | number[]requiredmessagestringrequiredUnauthorized
errorstringrequiredContact not found
errorstringrequiredInternal server error
errorstringrequiredcurl -X PATCH "https://api.callshift.ai/v1/contact/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer $CALLSHIFT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Ada",
"metadata": {
"plan": "pro",
"renewal": "2026-11-15"
}
}'const res = await fetch("https://api.callshift.ai/v1/contact/550e8400-e29b-41d4-a716-446655440000", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"firstName": "Ada",
"metadata": {
"plan": "pro",
"renewal": "2026-11-15"
}
}),
});
const data = await res.json();import os
import requests
res = requests.patch(
"https://api.callshift.ai/v1/contact/550e8400-e29b-41d4-a716-446655440000",
headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
json={
"firstName": "Ada",
"metadata": {
"plan": "pro",
"renewal": "2026-11-15",
},
},
)
print(res.json()){
"success": true
}{
"success": false,
"error": {
"name": "ZodError",
"issues": [
{
"code": "invalid_enum_value",
"path": [
"contacts",
0,
"email"
],
"message": "Invalid email"
}
]
}
}{
"error": "Authentication error"
}{
"error": "Contact not found"
}{
"error": "Internal server error"
}Mark contact as opted out
/v1/contact-opted-outMark a contact as opted out by phone number.
Authorization
AuthorizationstringrequiredBearer <API key>, a key created at app.callshift.ai/api-keys.
Body application/json
phoneNumberstringrequiredResponses
Contact marked as opted out
successbooleanrequiredInvalid request body
successenum<boolean>requiredfalseerrorobjectrequiredShow child attributes
nameenum<string>requiredZodErrorissuesobject[]requiredShow child attributes
codestringrequiredpathstring | number[]requiredmessagestringrequiredUnauthorized
errorstringrequiredContact not found
errorstringrequiredInternal server error
errorstringrequiredcurl -X POST "https://api.callshift.ai/v1/contact-opted-out" \
-H "Authorization: Bearer $CALLSHIFT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+33612345678"
}'const res = await fetch("https://api.callshift.ai/v1/contact-opted-out", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CALLSHIFT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"phoneNumber": "+33612345678"
}),
});
const data = await res.json();import os
import requests
res = requests.post(
"https://api.callshift.ai/v1/contact-opted-out",
headers={"Authorization": f"Bearer {os.environ['CALLSHIFT_API_KEY']}"},
json={
"phoneNumber": "+33612345678",
},
)
print(res.json()){
"success": true
}{
"success": false,
"error": {
"name": "ZodError",
"issues": [
{
"code": "invalid_enum_value",
"path": [
"contacts",
0,
"email"
],
"message": "Invalid email"
}
]
}
}{
"error": "Authentication error"
}{
"error": "Contact not found"
}{
"error": "Internal server error"
}