# Blocked callers

Numbers and prefixes whose inbound calls are turned away before your receptionist answers (spam, robocallers). Reading needs `dnc:read`, changes need `dnc:write`.

Base URL: `https://vocenya.com/api/public/v1`. Authenticate with `Authorization: Bearer $VOCENYA_API_KEY`.

- [List blocked callers](#list-blocked-callers): `GET /blocked-callers`
- [Block a caller](#create-blocked-caller): `POST /blocked-callers`
- [Unblock a caller](#delete-blocked-caller): `DELETE /blocked-callers/{entry}`

## List blocked callers

`GET https://vocenya.com/api/public/v1/blocked-callers`

Required scope: `dnc:read`

Your blocked callers, newest first. Pass `pattern` to look up one number or prefix.

### Query parameters

- `pattern` (string, optional): Look up one number (any common US format) or prefix (digits ending in `*`). Up to 32 characters.
- `source` (string, optional): `manual` (you added it), `ai` (the receptionist blocked a spam caller) or `call` (blocked from a call's page). | | |---| | `manual` <br/> Typed in on the blocked callers page or sent through the API. | | `ai` <br/> The AI receptionist judged a call spam and blocked the number. | | `call` <br/> Blocked from a call's page. | One of: `manual`, `ai`, `call`.
- `per_page` (integer, optional): How many items per page, 1 to 100. Minimum 1. Maximum 100.
- `cursor` (string or null, optional): The `meta.next_cursor` (or `meta.prev_cursor`) of the previous page. Up to 1024 characters.

### Responses

- `200`: Paginated set of `BlockedCallerResource`
- `401`: The API key is missing, invalid, expired or revoked.
- `403`: The key does not have the `dnc:read` scope.
- `422`: Validation error
- `429`: Too many requests for this key. Wait for the `Retry-After` seconds.

### Response attributes (200)

- `data` (array of objects, required)
  - `id` (integer, required)
  - `livemode` (boolean, required): `true` for live data, `false` for test data (created with a `vk_test_` key).
  - `pattern` (string, required): An E.164 number, or a prefix ending in `*` that blocks every number starting with it.
  - `source` (string, required): `manual` when you added it, `ai` when the receptionist blocked a spam caller, `call` when blocked from a call's page. | | |---| | `manual` <br/> Typed in on the blocked callers page or sent through the API. | | `ai` <br/> The AI receptionist judged a call spam and blocked the number. | | `call` <br/> Blocked from a call's page. | One of: `manual`, `ai`, `call`.
  - `note` (string or null, required)
  - `calls_blocked` (integer, required): How many calls this entry has turned away.
  - `last_blocked_at` (string or null, required)
  - `created_at` (string or null, required)
- `links` (object, required)
  - `first` (string or null, required)
  - `last` (string or null, required)
  - `prev` (string or null, required)
  - `next` (string or null, required)
- `meta` (object, required)
  - `path` (string or null, required): Base path for paginator generated URLs.
  - `per_page` (integer, required): Number of items shown per page. Minimum 0.
  - `next_cursor` (string or null, required): The "cursor" that points to the next set of items.
  - `prev_cursor` (string or null, required): The "cursor" that points to the previous set of items.

### Example request

```bash
curl https://vocenya.com/api/public/v1/blocked-callers \
  -H "Authorization: Bearer $VOCENYA_API_KEY"
```

```javascript
const response = await fetch('https://vocenya.com/api/public/v1/blocked-callers', {
  headers: {
    Authorization: `Bearer ${process.env.VOCENYA_API_KEY}`,
  },
});

const data = await response.json();
console.log(data);
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://vocenya.com/api/public/v1/blocked-callers', [
    'headers' => ['Authorization' => 'Bearer '.getenv('VOCENYA_API_KEY')],
]);

$data = json_decode((string) $response->getBody(), true);
print_r($data);
```

```python
import os

import requests

response = requests.get(
    "https://vocenya.com/api/public/v1/blocked-callers",
    headers={"Authorization": f"Bearer {os.environ['VOCENYA_API_KEY']}"},
)

print(response.json())
```

### Example response (200)

```json
{
  "data": [
    {
      "id": 1,
      "livemode": true,
      "pattern": "+15125550123",
      "source": "manual",
      "note": "string",
      "calls_blocked": 1,
      "last_blocked_at": "2026-10-02T14:03:11+00:00",
      "created_at": "2026-10-02T14:03:11+00:00"
    }
  ],
  "links": {
    "first": "string",
    "last": "string",
    "prev": "string",
    "next": "string"
  },
  "meta": {
    "path": "string",
    "per_page": 1,
    "next_cursor": "string",
    "prev_cursor": "string"
  }
}
```


## Block a caller

`POST https://vocenya.com/api/public/v1/blocked-callers`

Required scope: `dnc:write`

Block a number, or every number starting with a prefix (`512555*`). Adding a pattern already on the list
returns the existing entry with status 200.

### Request body

- `pattern` (string, required): A US phone number in any common format, or a prefix of at least four digits ending in `*` to block every number starting with it. Up to 32 characters.
- `note` (string or null, optional): Up to 255 characters.

### Responses

- `200`: The pattern was already on the list: the existing entry.
- `201`: The entry.
- `401`: The API key is missing, invalid, expired or revoked.
- `403`: The key does not have the `dnc:write` scope.
- `422`: Validation failed, or the pattern is neither a US number nor a prefix (`invalid_pattern`).
- `429`: Too many requests for this key. Wait for the `Retry-After` seconds.

### Response attributes (200)

- `data` (object, required)
  - `id` (integer, required)
  - `livemode` (boolean, required): `true` for live data, `false` for test data (created with a `vk_test_` key).
  - `pattern` (string, required): An E.164 number, or a prefix ending in `*` that blocks every number starting with it.
  - `source` (string, required): `manual` when you added it, `ai` when the receptionist blocked a spam caller, `call` when blocked from a call's page. | | |---| | `manual` <br/> Typed in on the blocked callers page or sent through the API. | | `ai` <br/> The AI receptionist judged a call spam and blocked the number. | | `call` <br/> Blocked from a call's page. | One of: `manual`, `ai`, `call`.
  - `note` (string or null, required)
  - `calls_blocked` (integer, required): How many calls this entry has turned away.
  - `last_blocked_at` (string or null, required)
  - `created_at` (string or null, required)

### Example request

```bash
curl -X POST https://vocenya.com/api/public/v1/blocked-callers \
  -H "Authorization: Bearer $VOCENYA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "pattern": "string",
  "note": "Robocaller"
}'
```

```javascript
const response = await fetch('https://vocenya.com/api/public/v1/blocked-callers', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.VOCENYA_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "pattern": "string",
    "note": "Robocaller"
  }),
});

const data = await response.json();
console.log(data);
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://vocenya.com/api/public/v1/blocked-callers', [
    'headers' => ['Authorization' => 'Bearer '.getenv('VOCENYA_API_KEY')],
    'json' => [
        'pattern' => 'string',
        'note' => 'Robocaller',
    ],
]);

$data = json_decode((string) $response->getBody(), true);
print_r($data);
```

```python
import os

import requests

response = requests.post(
    "https://vocenya.com/api/public/v1/blocked-callers",
    headers={"Authorization": f"Bearer {os.environ['VOCENYA_API_KEY']}"},
    json={
        "pattern": "string",
        "note": "Robocaller",
    },
)

print(response.json())
```

### Example response (200)

```json
{
  "data": {
    "id": 1,
    "livemode": true,
    "pattern": "+15125550123",
    "source": "manual",
    "note": "string",
    "calls_blocked": 1,
    "last_blocked_at": "2026-10-02T14:03:11+00:00",
    "created_at": "2026-10-02T14:03:11+00:00"
  }
}
```


## Unblock a caller

`DELETE https://vocenya.com/api/public/v1/blocked-callers/{entry}`

Required scope: `dnc:write`

### Path parameters

- `entry` (integer, required): The entry id.

### Responses

- `204`: Removed.
- `401`: The API key is missing, invalid, expired or revoked.
- `403`: The key does not have the `dnc:write` scope.
- `404`: No record with that id belongs to your account.
- `429`: Too many requests for this key. Wait for the `Retry-After` seconds.

### Example request

```bash
curl -X DELETE https://vocenya.com/api/public/v1/blocked-callers/31 \
  -H "Authorization: Bearer $VOCENYA_API_KEY"
```

```javascript
const response = await fetch('https://vocenya.com/api/public/v1/blocked-callers/31', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${process.env.VOCENYA_API_KEY}`,
  },
});

console.log(response.status);
```

```php
$client = new \GuzzleHttp\Client();

$response = $client->request('DELETE', 'https://vocenya.com/api/public/v1/blocked-callers/31', [
    'headers' => ['Authorization' => 'Bearer '.getenv('VOCENYA_API_KEY')],
]);

echo $response->getStatusCode();
```

```python
import os

import requests

response = requests.delete(
    "https://vocenya.com/api/public/v1/blocked-callers/31",
    headers={"Authorization": f"Bearer {os.environ['VOCENYA_API_KEY']}"},
)

print(response.status_code)
```

