# API: Phone numbers and calls

| Method | Path | What it does | Scope |
|---|---|---|---|
| POST | `/v1/telephony/telnyx/voice/:connection` | Telnyx voice webhooks (public; Ed25519-signed over {telnyx-timestamp}\|{raw body}, 5-minute window; the event's connection must be the organization's; each event applied once) (no sign-in) | — |
| POST | `/v1/telephony/twilio/voice/:org` | Twilio voice status, AMD and recording callbacks (public; X-Twilio-Signature HMAC-SHA1 over the URL and form fields with the organization's own auth token; its own Account SID only; each event once) (no sign-in) | — |
| GET | `/v1/voice` | Voice: connections, numbers (purpose, caps, health, CNAM, registry), pools, porting orders, concurrency (budget, in use, platform ceiling), countries and the voice webhook URL | `settings:read` |
| POST | `/v1/voice/branded` | Submit the branded-calling identity (owner; Telnyx Branded Calling, paid: $50 setup metered with you as approver; only when turned on) (web app only) | `settings:write` |
| POST | `/v1/voice/caller-ids` | Verify a number you have at another carrier as caller ID (owner; Telnyx calls or texts it a code; calls from it get STIR/SHAKEN attestation B) (web app only) | `settings:write` |
| POST | `/v1/voice/caller-ids/:id/verify` | Enter the verification code for a caller ID (owner) (web app only) | `settings:write` |
| GET | `/v1/voice/calls` | Calls, newest first (optionally one contact's or one number's) | `calls:read` |
| POST | `/v1/voice/calls` | Place a call as yourself (the calling rules, caller ID, the concurrency budget and the telephony budget apply; quiet hours queue it) (web app only) | `messages:send` |
| GET | `/v1/voice/calls/:id` | One call: status, timestamps, AMD result, recording, disclosure version, cost | `transcripts:read` |
| POST | `/v1/voice/connections` | Add the Telnyx Call Control application or your own SIP connection (owner; checked on your Telnyx account; a SIP password is stored encrypted) | `integrations:write` |
| DELETE | `/v1/voice/connections/:id` | Turn a voice connection off (owner) | `integrations:write` |
| POST | `/v1/voice/countries/:country` | Start enabling calls and numbers in a country (owner): the carrier's requirements for it | `settings:write` |
| PUT | `/v1/voice/countries/:country/documents` | Your answers to a country's requirements: Telnyx document or address ids, or text (owner) | `settings:write` |
| POST | `/v1/voice/countries/:country/enable` | Enable or disable a country for calls (owner; every requirement needs an answer first) | `settings:write` |
| PATCH | `/v1/voice/numbers/:id` | A number's voice settings (owner): on/off, inbound / outbound / both, daily call cap, connection, branded | `settings:write` |
| POST | `/v1/voice/numbers/:id/cnam` | Set the caller name (CNAM, 15 characters) on a US number hosted on your account (owner) | `settings:write` |
| POST | `/v1/voice/numbers/:id/reputation` | Check a number's spam reputation now (owner; Telnyx Number Reputation, paid, only when turned on; high risk rests the number) | `settings:write` |
| POST | `/v1/voice/numbers/:id/restore` | Put a rested (flagged) number back into rotation after remediation (owner) | `settings:write` |
| POST | `/v1/voice/numbers/buy` | Buy a number (owner; costs money: metered on the telephony budget with you as approver, audited) (web app only) | `settings:write` |
| POST | `/v1/voice/numbers/enable` | Run voice on one of your existing Telnyx numbers (owner; checked on your account first) | `settings:write` |
| POST | `/v1/voice/numbers/import` | Run voice on every number already on your Telnyx account (owner) | `settings:write` |
| GET | `/v1/voice/numbers/search` | Search numbers to buy on your Telnyx account (owner; free): country, area code, locality, type, features | `settings:write` |
| POST | `/v1/voice/pools` | Create a number pool for rotation (owner): default, per campaign or per rep, with local presence | `settings:write` |
| DELETE | `/v1/voice/pools/:id` | Delete a number pool (owner; the numbers stay) | `settings:write` |
| PUT | `/v1/voice/pools/:id` | Change a number pool and its numbers (owner) | `settings:write` |
| POST | `/v1/voice/ports` | Start porting numbers in (owner): the portability check and a draft order | `settings:write` |
| POST | `/v1/voice/ports/:id/refresh` | Check a porting order's status with Telnyx (owner); ported numbers join for voice | `settings:write` |
| POST | `/v1/voice/ports/:id/submit` | Submit a porting order with the losing carrier's account details (owner; the LOA) (web app only) | `settings:write` |
| POST | `/v1/voice/registry` | Record that numbers were submitted to the Free Caller Registry, and when (owner) | `settings:write` |
| PUT | `/v1/voice/settings` | Voice settings (owner): concurrent calls and the inbound reserve, the international daily cap, branded calling and number reputation (paid, off by default), spam-signal thresholds, default CNAM | `settings:write` |

## Examples

### GET /v1/voice

Voice: connections, numbers (purpose, caps, health, CNAM, registry), pools, porting orders, concurrency (budget, in use, platform ceiling), countries and the voice webhook URL

```bash
curl -s "https://api.closefinch.com/v1/voice" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/voice/calls

Calls, newest first (optionally one contact's or one number's)

```bash
curl -s "https://api.closefinch.com/v1/voice/calls" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/calls`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### GET /v1/voice/calls/$ID

One call: status, timestamps, AMD result, recording, disclosure version, cost

```bash
curl -s "https://api.closefinch.com/v1/voice/calls/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/calls/${id}`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/voice/connections

Add the Telnyx Call Control application or your own SIP connection (owner; checked on your Telnyx account; a SIP password is stored encrypted)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/connections" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/connections`, {
  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/connections/$ID

Turn a voice connection off (owner)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/voice/connections/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/connections/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/voice/countries/$COUNTRY

Start enabling calls and numbers in a country (owner): the carrier's requirements for it

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/countries/$COUNTRY" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/countries/${country}`, {
  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();
```

### PUT /v1/voice/countries/$COUNTRY/documents

Your answers to a country's requirements: Telnyx document or address ids, or text (owner)

```bash
curl -s -X PUT "https://api.closefinch.com/v1/voice/countries/$COUNTRY/documents" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/countries/${country}/documents`, {
  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/countries/$COUNTRY/enable

Enable or disable a country for calls (owner; every requirement needs an answer first)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/countries/$COUNTRY/enable" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/countries/${country}/enable`, {
  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();
```

### PATCH /v1/voice/numbers/$ID

A number's voice settings (owner): on/off, inbound / outbound / both, daily call cap, connection, branded

```bash
curl -s -X PATCH "https://api.closefinch.com/v1/voice/numbers/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/${id}`, {
  method: "PATCH",
  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/numbers/$ID/cnam

Set the caller name (CNAM, 15 characters) on a US number hosted on your account (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/numbers/$ID/cnam" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/${id}/cnam`, {
  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();
```

### POST /v1/voice/numbers/$ID/reputation

Check a number's spam reputation now (owner; Telnyx Number Reputation, paid, only when turned on; high risk rests the number)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/numbers/$ID/reputation" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/${id}/reputation`, {
  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();
```

### POST /v1/voice/numbers/$ID/restore

Put a rested (flagged) number back into rotation after remediation (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/numbers/$ID/restore" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/${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();
```

### POST /v1/voice/numbers/enable

Run voice on one of your existing Telnyx numbers (owner; checked on your account first)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/numbers/enable" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/enable`, {
  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();
```

### POST /v1/voice/numbers/import

Run voice on every number already on your Telnyx account (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/numbers/import" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/import`, {
  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/numbers/search

Search numbers to buy on your Telnyx account (owner; free): country, area code, locality, type, features

```bash
curl -s "https://api.closefinch.com/v1/voice/numbers/search" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/numbers/search`, {
  method: "GET",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### POST /v1/voice/pools

Create a number pool for rotation (owner): default, per campaign or per rep, with local presence

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/pools" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/pools`, {
  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/pools/$ID

Delete a number pool (owner; the numbers stay)

```bash
curl -s -X DELETE "https://api.closefinch.com/v1/voice/pools/$ID" \
  -H "Authorization: Bearer $RA_API_KEY"
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/pools/${id}`, {
  method: "DELETE",
  headers: { authorization: `Bearer ${process.env.RA_API_KEY}` },
});
const data = await res.json();
```

### PUT /v1/voice/pools/$ID

Change a number pool and its numbers (owner)

```bash
curl -s -X PUT "https://api.closefinch.com/v1/voice/pools/$ID" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/pools/${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/ports

Start porting numbers in (owner): the portability check and a draft order

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/ports" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/ports`, {
  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();
```

### POST /v1/voice/ports/$ID/refresh

Check a porting order's status with Telnyx (owner); ported numbers join for voice

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/ports/$ID/refresh" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/ports/${id}/refresh`, {
  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();
```

### POST /v1/voice/registry

Record that numbers were submitted to the Free Caller Registry, and when (owner)

```bash
curl -s -X POST "https://api.closefinch.com/v1/voice/registry" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/registry`, {
  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();
```

### PUT /v1/voice/settings

Voice settings (owner): concurrent calls and the inbound reserve, the international daily cap, branded calling and number reputation (paid, off by default), spam-signal thresholds, default CNAM

```bash
curl -s -X PUT "https://api.closefinch.com/v1/voice/settings" \
  -H "Authorization: Bearer $RA_API_KEY" \
  -H "content-type: application/json" \
  -d '{}'
```

```js
const res = await fetch(`https://api.closefinch.com/v1/voice/settings`, {
  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();
```

Request and response schemas: [https://www.closefinch.com/openapi.json](https://www.closefinch.com/openapi.json). All resources: [API reference](https://www.closefinch.com/docs/api).
