API reference
API: Phone menus and transfers
| Method | Path | What it does | Scope |
|---|---|---|---|
| GET | /v1/voice/ivr/menus | Phone menus (hosted IVR) per number, and the numbers that can take one | settings:read |
| POST | /v1/voice/ivr/menus | Create a phone menu (owner): menus (keys or spoken words), messages, a business-hours branch; routes to the voice agent, a ring group, voicemail or another node. Off until enabled | settings:write |
| DELETE | /v1/voice/ivr/menus/:id | Delete a phone menu (owner): the number's own inbound routing answers again | settings:write |
| PUT | /v1/voice/ivr/menus/:id | Change a phone menu (owner): saved as a new version | settings:write |
| POST | /v1/voice/ivr/menus/:id/restore | Publish an older version again (owner), as a new version | settings:write |
| GET | /v1/voice/ivr/menus/:id/versions | A phone menu's versions (newest first) | settings:read |
| GET | /v1/voice/ivr/navigations | Recent phone-tree navigations: goal, each menu heard and key pressed, and how it ended | calls:read |
| POST | /v1/voice/ivr/navigations | Call a company and navigate its phone tree to a person (sales, support, the operator, someone by name). Placed through the calling gate (window, opt-outs, do-not-call, consent, caller ID, policy); call_id instead navigates a call already live | messages:send |
| GET | /v1/voice/ivr/paths | Learned phone-tree paths per company number and goal (replayed on the next call, re-learned when the menu changes) | calls:read |
| DELETE | /v1/voice/ivr/paths/:id | Forget a learned path (owner) | settings:write |
| GET | /v1/voice/ivr/sessions | Recent calls through a phone menu: the path taken (keys, words, retries) and the route | calls:read |
| POST | /v1/voice/ivr/simulate | Try a phone menu without a call: its problems, and what happens to a caller who presses these keys or says these words | settings:read |
| GET | /v1/voice/transfer/queues | Transfer queues: who the AI hands live calls to (account owner first, then members by skill, round-robin), seconds to accept, attempts, fallback | settings:read |
| POST | /v1/voice/transfer/queues | Add a transfer queue (owner) | settings:write |
| DELETE | /v1/voice/transfer/queues/:id | Delete a transfer queue (owner) | settings:write |
| PUT | /v1/voice/transfer/queues/:id | Change a transfer queue (owner) | settings:write |
| GET | /v1/voice/transfers | Recent warm transfers with their legs and timings, and time to a person (p50/p95) and the success rate | calls:read |
| POST | /v1/voice/transfers | Hand a live call to a person now (warm: they get the context and accept with 1) | messages:send |
| GET | /v1/voice/transfers/:id | A transfer's screen pop: the caller, account, deal, reason, summary and transcript so far (withheld when the caller objected to recording), every leg | transcripts:read |
| POST | /v1/voice/transfers/:id/pass | Pass on a transfer ringing you (the next person is rung) | calls:write |
Examples
GET /v1/voice/ivr/menus
Phone menus (hosted IVR) per number, and the numbers that can take one
curl -s "https://api.closefinch.com/v1/voice/ivr/menus" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/ivr/menus
Create a phone menu (owner): menus (keys or spoken words), messages, a business-hours branch; routes to the voice agent, a ring group, voicemail or another node. Off until enabled
curl -s -X POST "https://api.closefinch.com/v1/voice/ivr/menus" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();DELETE /v1/voice/ivr/menus/$ID
Delete a phone menu (owner): the number's own inbound routing answers again
curl -s -X DELETE "https://api.closefinch.com/v1/voice/ivr/menus/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PUT /v1/voice/ivr/menus/$ID
Change a phone menu (owner): saved as a new version
curl -s -X PUT "https://api.closefinch.com/v1/voice/ivr/menus/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus/${id}`, {
method: "PUT",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();POST /v1/voice/ivr/menus/$ID/restore
Publish an older version again (owner), as a new version
curl -s -X POST "https://api.closefinch.com/v1/voice/ivr/menus/$ID/restore" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus/${id}/restore`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();GET /v1/voice/ivr/menus/$ID/versions
A phone menu's versions (newest first)
curl -s "https://api.closefinch.com/v1/voice/ivr/menus/$ID/versions" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/menus/${id}/versions`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/voice/ivr/navigations
Recent phone-tree navigations: goal, each menu heard and key pressed, and how it ended
curl -s "https://api.closefinch.com/v1/voice/ivr/navigations" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/navigations`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/ivr/navigations
Call a company and navigate its phone tree to a person (sales, support, the operator, someone by name). Placed through the calling gate (window, opt-outs, do-not-call, consent, caller ID, policy); call_id instead navigates a call already live
curl -s -X POST "https://api.closefinch.com/v1/voice/ivr/navigations" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/navigations`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();GET /v1/voice/ivr/paths
Learned phone-tree paths per company number and goal (replayed on the next call, re-learned when the menu changes)
curl -s "https://api.closefinch.com/v1/voice/ivr/paths" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/paths`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();DELETE /v1/voice/ivr/paths/$ID
Forget a learned path (owner)
curl -s -X DELETE "https://api.closefinch.com/v1/voice/ivr/paths/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/paths/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();GET /v1/voice/ivr/sessions
Recent calls through a phone menu: the path taken (keys, words, retries) and the route
curl -s "https://api.closefinch.com/v1/voice/ivr/sessions" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/sessions`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/ivr/simulate
Try a phone menu without a call: its problems, and what happens to a caller who presses these keys or says these words
curl -s -X POST "https://api.closefinch.com/v1/voice/ivr/simulate" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/ivr/simulate`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();GET /v1/voice/transfer/queues
Transfer queues: who the AI hands live calls to (account owner first, then members by skill, round-robin), seconds to accept, attempts, fallback
curl -s "https://api.closefinch.com/v1/voice/transfer/queues" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/transfer/queues`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/transfer/queues
Add a transfer queue (owner)
curl -s -X POST "https://api.closefinch.com/v1/voice/transfer/queues" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/transfer/queues`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();DELETE /v1/voice/transfer/queues/$ID
Delete a transfer queue (owner)
curl -s -X DELETE "https://api.closefinch.com/v1/voice/transfer/queues/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/transfer/queues/${id}`, {
method: "DELETE",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();PUT /v1/voice/transfer/queues/$ID
Change a transfer queue (owner)
curl -s -X PUT "https://api.closefinch.com/v1/voice/transfer/queues/$ID" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/transfer/queues/${id}`, {
method: "PUT",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();GET /v1/voice/transfers
Recent warm transfers with their legs and timings, and time to a person (p50/p95) and the success rate
curl -s "https://api.closefinch.com/v1/voice/transfers" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/transfers`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/transfers
Hand a live call to a person now (warm: they get the context and accept with 1)
curl -s -X POST "https://api.closefinch.com/v1/voice/transfers" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/transfers`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();GET /v1/voice/transfers/$ID
A transfer's screen pop: the caller, account, deal, reason, summary and transcript so far (withheld when the caller objected to recording), every leg
curl -s "https://api.closefinch.com/v1/voice/transfers/$ID" \
-H "Authorization: Bearer $RA_API_KEY"const res = await fetch(`https://api.closefinch.com/v1/voice/transfers/${id}`, {
method: "GET",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();POST /v1/voice/transfers/$ID/pass
Pass on a transfer ringing you (the next person is rung)
curl -s -X POST "https://api.closefinch.com/v1/voice/transfers/$ID/pass" \
-H "Authorization: Bearer $RA_API_KEY" \
-H "content-type: application/json" \
-d '{}'const res = await fetch(`https://api.closefinch.com/v1/voice/transfers/${id}/pass`, {
method: "POST",
headers: { authorization: `Bearer ${process.env.RA_API_KEY}`, "content-type": "application/json" },
body: JSON.stringify({}), // fields: see the OpenAPI schema
});
const data = await res.json();Request and response schemas: https://www.closefinch.com/openapi.json. All resources: API reference.