Calling
Phone numbers, calls, recordings and call notes.
Call a person from the browser
/v1/calling/callscalling.calls-createNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Body { personId, toNumber?, fromNumberId?, callTaskId?, touchId?, recording? }. toNumber must be one of the person's phones (400 invalid_phone); absent, Kenso calls their primary phone. fromNumberId absent takes the member's number, else the workspace's first. callTaskId must be an open call task of the person (400). touchId must be a call touch of the person (400; 404 when there is none), and the call's outcome closes it; send callTaskId or touchId, not both (400). Kenso rings the member's browser first (log in with POST /v1/calling/tokens) and dials the person when the browser answers; status is ringing_rep. Kenso holds 10 minutes at millicreditsPerMinute and charges started minutes when the call ends. A refused call is 422 call_refused with the reason in details[0].code (outside_calling_hours, opted_out, no_phone, ...) and, for the time-bound reasons, nextAllowedAt. 402 insufficient_credits, calling_limit_reached (the monthly calling spend limit) or member_credit_limit_reached; 404 for a person of another workspace; 503 provider_unavailable when the carrier is not set up or does not take the call (nothing is charged), 503 try_again with Retry-After when another call of the workspace is starting. Requires edit on the Accounts page.
Parameters
400 workspace_required).Request body
application/json, optional.
Response 200
data is a CallingCallModel.
ringing_rep while the member's browser rings.mobile or fixed_line.off, manual or auto, from the workspace's setting and the line type. Not off: Kenso listens for a voicemail beep, and a greeting can be dropped (manual: with POST .../voicemail-drop; auto: the member's oldest greeting drops by itself).curl -X POST "https://api.ken.so/v1/calling/calls" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"personId": 812,
"toNumber": "string",
"fromNumberId": 812,
"callTaskId": 812,
"touchId": 812,
"recording": true
}'{
"success": true,
"data": {
"callId": 812,
"status": "string",
"to": "string",
"from": "string",
"fromNumberId": 812,
"millicreditsPerMinute": 1,
"consentNoticeWillPlay": true,
"recordingAllowed": true,
"lineType": "string",
"voicemailDropMode": "string"
}
}Hang up a browser call
/v1/calling/calls/{callId}/hangupcalling.calls-hangupNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Hangs up every leg of the call that is still up and answers 202 with its status; the call ends when the carrier confirms. A call that already ended answers 200 with its final status. Only the member who placed the call may hang it up (403); a call of another workspace, or one not placed in Kenso, is 404. Requires edit on the Accounts page.
Parameters
400 workspace_required).Response 200
Also answers 202. data is a CallingHangupModel.
curl -X POST "https://api.ken.so/v1/calling/calls/812/hangup" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"callId": 812,
"status": "string"
}
}Drop a voicemail greeting on a browser call
/v1/calling/calls/{callId}/voicemail-dropcalling.calls-voicemail-dropNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Body { voicemailId? }: one of your greetings, absent your oldest. The call must be one you placed that the other side answered, with a voicemailDropMode other than off. Kenso waits for the voicemail's beep, hangs up your side, plays the greeting and then hangs up; the call is logged with the voicemail disposition. When detection heard no machine (amdResulthuman or not_sure) no beep comes, so a drop you ask for plays at once: ask after the beep you hear. Answers 202 with voicemailDropStatus (requested, starting, playing or failed), 200 once it is dropped; asking again while a drop is under way answers its state. Do not hang up the call yourself after a drop: that ends the greeting. 409 invalid_state for a call that ended, was not answered or has drops off, 409 no_voicemail when you named none and have none, 404 for a greeting that is not yours, 403 for a call you did not place, 503 provider_unavailable when the audio store or the carrier is not set up. Requires edit on the Accounts page.
Parameters
400 workspace_required).Request body
application/json, optional.
Response 200
Also answers 202. data is a CallingVoicemailDropModel.
requested (waiting for the beep, which never comes when detection heard no machine: a drop you ask for then plays at once), starting (Kenso is hanging up your side), playing, dropped or failed.curl -X POST "https://api.ken.so/v1/calling/calls/812/voicemail-drop" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"voicemailId": 812
}'{
"success": true,
"data": {
"callId": 812,
"voicemailId": 812,
"voicemailDropStatus": "string"
}
}Create a WebRTC login token for the member's browser
/v1/calling/tokenscalling.tokens-createNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Returns { token, sipUsername, expiresAt } on the member's own carrier credential; the browser logs in with it to answer the calls it starts. The token is a secret: keep it in memory. 422 call_refused (calling_disabled) while calling is off, 503 provider_unavailable when the carrier is not set up or not reachable. Requires edit on the Accounts page.
Parameters
400 workspace_required).Response 200
data is a CallingTokenModel.
curl -X POST "https://api.ken.so/v1/calling/tokens" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"token": "string",
"sipUsername": "string",
"expiresAt": "2026-09-23T15:02:11Z"
}
}Return the workspace's calling settings
/v1/calling/settingscalling.settings-getNeeds the calling feature on your workspace. Until it is on, calls answer 404.
A workspace that never saved them gets the defaults and updatedAt null. Requires ReadAccess.
Parameters
400 workspace_required).Response 200
data is a CallingSettingsModel.
auto (where the law asks for it), always or never.off, manual (the rep drops one) or auto.acceptTcpaNotice: true.curl -X GET "https://api.ken.so/v1/calling/settings" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"recordingEnabled": true,
"consentNotice": "string",
"voicemailDropMode": "string",
"voicemailToMobile": true,
"voicemailToMobileAcceptedByMemberId": 812,
"voicemailToMobileAcceptedAt": "2026-09-23T15:02:11Z",
"allowedCountries": [
"string"
],
"dncScrub": true,
"updatedAt": "2026-09-23T15:02:11Z"
}
}Update the workspace's calling settings
/v1/calling/settingscalling.settings-updateNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Absent fields stay unchanged; null is not allowed. consentNotice is auto, always or never; voicemailDropMode is off, manual or auto; allowedCountries is a non-empty list of US and CA. voicemailToMobile: true needs acceptTcpaNotice: true in the same body (400 validation_failed on acceptTcpaNotice otherwise), which records who accepted and when; turning it off keeps that record. Requires the workspace_settings feature.
Parameters
400 workspace_required).Request body
application/json, optional: object.
Response 200
data is a CallingSettingsModel.
auto (where the law asks for it), always or never.off, manual (the rep drops one) or auto.acceptTcpaNotice: true.curl -X PATCH "https://api.ken.so/v1/calling/settings" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{}'{
"success": true,
"data": {
"recordingEnabled": true,
"consentNotice": "string",
"voicemailDropMode": "string",
"voicemailToMobile": true,
"voicemailToMobileAcceptedByMemberId": 812,
"voicemailToMobileAcceptedAt": "2026-09-23T15:02:11Z",
"allowedCountries": [
"string"
],
"dncScrub": true,
"updatedAt": "2026-09-23T15:02:11Z"
}
}List the workspace's phone numbers
/v1/calling/numberscalling.numbers-listNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Every number not released, newest first, at most five. unpaid is true when its monthly credits could not be charged. Requires ReadAccess.
Parameters
400 workspace_required).Response 200
data is a list of CallingNumberModel. Each item has these fields. The response also carries pagination.
local (toll-free numbers are not sold yet).ordering, active, releasing or released.curl -X GET "https://api.ken.so/v1/calling/numbers" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [
{
"numberId": 812,
"e164": "string",
"countryIso2": "string",
"numberType": "string",
"status": "string",
"assignedMemberId": 812,
"cnam": "string",
"monthlyCredits": 1,
"unpaid": true,
"orderedAt": "2026-09-23T15:02:11Z",
"activatedAt": "2026-09-23T15:02:11Z",
"releasedAt": "2026-09-23T15:02:11Z"
}
],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"total": 1,
"isTotalCapped": true
}
}Buy a phone number
/v1/calling/numberscalling.numbers-buyNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Buys a local number for 100 credits a month; the first month is charged when it is active. e164 is a number from numbers/available: when a fresh search no longer offers it, the first number that search offers is bought. assignedMemberId must be an active member without a number (400 invalid_member, 409 member_already_has_number); cnam is at most 15 letters, digits, spaces and .,&-, US numbers only. 409 number_limit_reached at five numbers, 402 when the workspace cannot pay the first month, 409 no_numbers_available when the search finds none, 503 provider_unavailable when the carrier is not set up or refuses the order (nothing is charged). status is ordering while the carrier has not assigned the number. Toll-free numbers are not sold. Requires the workspace_settings and billing features: a number is a monthly charge.
Parameters
400 workspace_required).Request body
application/json, optional.
numbers/available. When a fresh search no longer offers it, the first number that search offers is bought instead.Response 201
data is a CallingNumberModel.
local (toll-free numbers are not sold yet).ordering, active, releasing or released.curl -X POST "https://api.ken.so/v1/calling/numbers" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{
"e164": "string",
"country": "string",
"areaCode": "string",
"locality": "string",
"assignedMemberId": 812,
"cnam": "string"
}'{
"success": true,
"data": {
"numberId": 812,
"e164": "string",
"countryIso2": "string",
"numberType": "string",
"status": "string",
"assignedMemberId": 812,
"cnam": "string",
"monthlyCredits": 1,
"unpaid": true,
"orderedAt": "2026-09-23T15:02:11Z",
"activatedAt": "2026-09-23T15:02:11Z",
"releasedAt": "2026-09-23T15:02:11Z"
}
}Search local numbers for sale
/v1/calling/numbers/availablecalling.numbers-availableNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Up to 10 local numbers in country (US or CA, and one the workspace calls), optionally in a three-digit areaCode or a locality. Each costs monthlyCredits credits a month once bought. 503 provider_unavailable when the carrier is not set up or not reachable. Requires the workspace_settings feature.
Parameters
US or CA.400 workspace_required).Response 200
data is a list of AvailableCallingNumberModel. Each item has these fields. The response also carries pagination.
curl -X GET "https://api.ken.so/v1/calling/numbers/available" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [
{
"e164": "string",
"countryIso2": "string",
"locality": "string",
"region": "string",
"monthlyCredits": 1
}
],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"total": 1,
"isTotalCapped": true
}
}Assign a phone number or set its caller name
/v1/calling/numbers/{numberId}calling.numbers-updateNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Absent fields stay unchanged. assignedMemberId null unassigns it; a member must be active in the workspace (400 invalid_member) and hold no other number (409 member_already_has_number). cnam null clears it; at most 15 letters, digits, spaces and .,&-, US numbers only. A caller name change goes to the carrier first (503 provider_unavailable when it does not take it). A number of another workspace is 404 not_found. Requires the workspace_settings feature.
Parameters
400 workspace_required).Request body
application/json, optional: object.
Response 200
data is a CallingNumberModel.
local (toll-free numbers are not sold yet).ordering, active, releasing or released.curl -X PATCH "https://api.ken.so/v1/calling/numbers/812" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{}'{
"success": true,
"data": {
"numberId": 812,
"e164": "string",
"countryIso2": "string",
"numberType": "string",
"status": "string",
"assignedMemberId": 812,
"cnam": "string",
"monthlyCredits": 1,
"unpaid": true,
"orderedAt": "2026-09-23T15:02:11Z",
"activatedAt": "2026-09-23T15:02:11Z",
"releasedAt": "2026-09-23T15:02:11Z"
}
}Release a phone number
/v1/calling/numbers/{numberId}calling.numbers-releaseNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Stops its monthly credits (the paid month is not refunded) and gives it back to the carrier. Returns the number released (also when the carrier no longer has it or never assigned it), or 202 with status: releasing when the carrier has not taken it back yet: the number stays releasing and finishes by itself once the number lifecycle job is on; until then the client may retry DELETE. A number of another workspace is 404 not_found. Requires the workspace_settings and billing features, like the buy.
Parameters
400 workspace_required).Response 200
Also answers 202. data is a CallingNumberModel.
local (toll-free numbers are not sold yet).ordering, active, releasing or released.curl -X DELETE "https://api.ken.so/v1/calling/numbers/812" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"numberId": 812,
"e164": "string",
"countryIso2": "string",
"numberType": "string",
"status": "string",
"assignedMemberId": 812,
"cnam": "string",
"monthlyCredits": 1,
"unpaid": true,
"orderedAt": "2026-09-23T15:02:11Z",
"activatedAt": "2026-09-23T15:02:11Z",
"releasedAt": "2026-09-23T15:02:11Z"
}
}Return what a call to a number costs
/v1/calling/ratescalling.rates-getNeeds the calling feature on your workspace. Until it is on, calls answer 404.
to is the number to call. millicreditsPerMinute is the destination rate plus the rep's leg, and recordingMillicreditsPerMinute is added when the call is recorded. A destination Kenso has no price for yet is priced: false with null rates; a value that is not a phone number is 400 invalid_phone. Requires ReadAccess.
Parameters
400 workspace_required).Response 200
data is a CallingRateModel.
mobile, fixed_line or fixed_line_or_mobile.curl -X GET "https://api.ken.so/v1/calling/rates" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"to": "string",
"countryIso2": "string",
"lineType": "string",
"priced": true,
"millicreditsPerMinute": 1,
"recordingMillicreditsPerMinute": 1
}
}Return the workspace's monthly calling spend limit
/v1/calling/spend-limitcalling.spend-limit-getNeeds the calling feature on your workspace. Until it is on, calls answer 404.
monthlyLimitMillicredits null is no limit; a workspace that never set it reads 2,000,000 (2,000 credits) with isDefault: true. spentThisMonthMillicredits is call minutes and recordings charged this UTC calendar month plus open call holds, the same spend the cap counts; number fees are not in it. Separate from /v1/spend-limits. Requires ReadAccess.
Parameters
400 workspace_required).Response 200
data is a CallingSpendLimitModel.
curl -X GET "https://api.ken.so/v1/calling/spend-limit" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": {
"monthlyLimitMillicredits": 1,
"isDefault": true,
"spentThisMonthMillicredits": 1
}
}Set the workspace's monthly calling spend limit
/v1/calling/spend-limitcalling.spend-limit-updateNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Body { "monthlyLimitMillicredits": number | null }: null is no limit, else 1 to 100,000,000 (400 validation_failed otherwise). The next call reads it. Returns the GET shape. Requires the workspace_settings and billing features.
Parameters
400 workspace_required).Request body
application/json, optional: object.
Response 200
data is a CallingSpendLimitModel.
curl -X PATCH "https://api.ken.so/v1/calling/spend-limit" \
-H "Authorization: Bearer $KEN_API_KEY" \
-H "Ken-Version: 2026-11-02" \
-H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
-H "Content-Type: application/json" \
-d '{}'{
"success": true,
"data": {
"monthlyLimitMillicredits": 1,
"isDefault": true,
"spentThisMonthMillicredits": 1
}
}List your voicemail greetings
/v1/calling/voicemailscalling.voicemails-listNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Your live greetings, oldest first: the first is the one an auto drop plays. audioUrl is a 5-minute link to listen to it, absent while Kenso's audio store is not set up. Requires ReadAccess.
Parameters
400 workspace_required).Response 200
data is a list of CallingVoicemailModel. Each item has these fields. The response also carries pagination.
wav or mp3.curl -X GET "https://api.ken.so/v1/calling/voicemails" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
{
"success": true,
"data": [
{
"voicemailId": 812,
"name": "string",
"durationSeconds": 1,
"format": "string",
"audioUrl": "https://example.com",
"createdAt": "2026-09-23T15:02:11Z"
}
],
"pagination": {
"nextCursor": "eyJpZCI6ODE1fQ",
"hasMore": true,
"total": 1,
"isTotalCapped": true
}
}Upload a voicemail greeting
/v1/calling/voicemailscalling.voicemails-createNeeds the calling feature on your workspace. Until it is on, calls answer 404.
multipart/form-data with file (a WAV or MP3 recording, at most 12 MiB and 60 seconds) and an optional name (at most 80 characters, blank is Voicemail). Kenso reads the format from the audio itself. 400 validation_failed on file with unsupported_audio (WebM, Ogg and anything else), unreadable_audio, too_long or invalid; 409 voicemail_limit_reached at five greetings; 503 provider_unavailable while Kenso's audio store is not set up. Bulk rate-limit class, like the other uploads. Requires edit on the Accounts page.
Parameters
400 workspace_required).Request body
multipart/form-data, optional.
Response 201
data is a CallingVoicemailModel.
wav or mp3.curl -X POST "https://api.ken.so/v1/calling/voicemails" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \ -F "file=@./file" \ -F 'name=string'
{
"success": true,
"data": {
"voicemailId": 812,
"name": "string",
"durationSeconds": 1,
"format": "string",
"audioUrl": "https://example.com",
"createdAt": "2026-09-23T15:02:11Z"
}
}Delete a voicemail greeting
/v1/calling/voicemails/{voicemailId}calling.voicemails-deleteNeeds the calling feature on your workspace. Until it is on, calls answer 404.
Deletes one of your greetings and its audio; a drop that has not played it yet fails. 404 for a greeting that is not yours or is already deleted. Requires edit on the Accounts page.
Parameters
400 workspace_required).Response 204
curl -X DELETE "https://api.ken.so/v1/calling/voicemails/812" \ -H "Authorization: Bearer $KEN_API_KEY" \ -H "Ken-Version: 2026-11-02" \ -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
HTTP/1.1 204 No Content