---
title: "Blocked Callers"
description: "Refuse inbound calls from specific caller numbers: blocked calls end before an agent answers and are not billed."
---

The blocklist is a per-organization list of caller numbers. When a listed
number calls any of your organization's phone numbers, ThunderPhone refuses the
call before an agent starts and hangs up. The attempt is not billed. It appears
in call history as a failed inbound call with `end_reason` `caller_blocked`,
zero duration and zero cost, and it sends the same completion webhooks as any
other failed call.

- Numbers are stored in E.164 form (`+14155550123`) and compared with the
  caller ID in E.164 form, so `+1 (415) 555-0123` and `14155550123` match the
  same entry.
- Calls with a withheld or anonymous caller ID are never matched.
- A caller blocked while a call is in progress is not cut off; the block
  applies to their next call.
- Outbound calls are not affected: you can still call a blocked number.
- [SIP address](/api-reference/sip-addresses) calls are checked too when the
  caller presents a phone number. A caller identified only by a SIP URI
  cannot be blocked.
- An organization can block up to 10,000 numbers.

## Endpoints

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/v1/blocked-callers` | List blocked callers |
| `POST` | `/v1/blocked-callers` | Block a caller |
| `POST` | `/v1/blocked-callers/bulk` | Block up to 500 callers at once |
| `DELETE` | `/v1/blocked-callers/{blocked_caller_id}` | Unblock a caller |

Any organization member can list blocked callers. Adding and removing them
requires an admin or owner. OAuth clients need `numbers:read` to list and
`numbers:write` to change the list.

## Blocked caller object

```json
{
  "id": 42,
  "number": "+14155550123",
  "note": "Robocaller",
  "created_by_email": "ops@example.com",
  "created_at": "2026-09-30T18:24:10.113Z"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer | Id used to unblock |
| `number` | string | Blocked caller number, E.164 |
| `note` | string | Optional note, up to 200 characters |
| `created_by_email` | string \| null | Who added it; null for a removed user |
| `created_at` | timestamp | ISO 8601 UTC |

## Number formats

Send numbers in E.164 (`+14155550123`). Spaces, dashes, dots and parentheses
are ignored. A national format such as `(415) 555-0123` is accepted only when
all of your organization's phone numbers are in one country; it is read as a
number in that country. Otherwise the request fails with
`400` and asks for the `+` and country code.

---

## List blocked callers

<CodeGroup>
```bash cURL
curl 'https://api.thunderphone.com/v1/blocked-callers?limit=50' \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

| Query parameter | Description |
|-----------------|-------------|
| `limit` | Page size, 1–200 (default 50) |
| `offset` | Number of entries to skip (default 0) |
| `search` | Case-insensitive match on part of the number or the note |
| `number` | One exact number, in any accepted format. Use it to check whether a caller is blocked |

Returns `{"count": <total matches>, "results": [...]}` with
[Blocked caller objects](#blocked-caller-object), newest first.

---

## Block a caller

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/blocked-callers \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"number": "+14155550123", "note": "Robocaller"}'
```

```python Python
blocked = requests.post(
    "https://api.thunderphone.com/v1/blocked-callers",
    headers={"Authorization": "Bearer sk_live_YOUR_API_KEY"},
    json={"number": "+14155550123", "note": "Robocaller"},
).json()
```
</CodeGroup>

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `number` | string | yes | Caller number; see [Number formats](#number-formats) |
| `note` | string | no | Up to 200 characters |

Returns `201 Created` with the [Blocked caller object](#blocked-caller-object).
Returns `400` when the number is invalid, when it is one of your
organization's own phone numbers, when it is already blocked
(`{"number": ["This number is already blocked."]}`), or when the organization
already blocks 10,000 numbers (`"code": "blocklist_limit_reached"`).

---

## Block several callers

Adds up to 500 numbers in one request and reports a result for each input, in
order. One bad entry does not fail the others.

<CodeGroup>
```bash cURL
curl -X POST https://api.thunderphone.com/v1/blocked-callers/bulk \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"numbers": ["+14155550123", "+14155550124", "not a number"], "note": "Spam wave"}'
```
</CodeGroup>

```json
{
  "added": 1,
  "already_blocked": 1,
  "invalid": 1,
  "limit_reached": 0,
  "results": [
    {"input": "+14155550123", "status": "added", "number": "+14155550123", "id": 43, "error": null},
    {"input": "+14155550124", "status": "already_blocked", "number": "+14155550124", "id": 12, "error": null},
    {"input": "not a number", "status": "invalid", "number": null, "id": null, "error": "Enter a phone number, for example +14155550123."}
  ]
}
```

| `status` | Meaning |
|----------|---------|
| `added` | Now blocked |
| `already_blocked` | Was already on the list, or repeats an earlier entry in the same request |
| `invalid` | Not a usable phone number, or one of your organization's own numbers; `error` says why |
| `limit_reached` | Not added because the organization reached 10,000 blocked numbers |

The optional `note` applies to every number added by the request.

---

## Unblock a caller

<CodeGroup>
```bash cURL
curl -X DELETE https://api.thunderphone.com/v1/blocked-callers/42 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```
</CodeGroup>

Returns `204 No Content`. Calls from the number are answered again from the
next call on.

---

## Related

<CardGroup cols={2}>
  <Card title="Manage blocked callers in the dashboard" icon="ban" href="/guides/organization-settings#blocked-callers">
    Add, paste and remove blocked numbers, or block a caller from call history.
  </Card>
  <Card title="Calls" icon="phone" href="/api-reference/calls">
    Blocked attempts appear with end reason `caller_blocked`.
  </Card>
</CardGroup>
