Inkbox

> # Documentation index
> Fetch the complete documentation index at: https://inkbox.ai/sitemap.xml
> Use this file to discover all available pages before exploring further.

---

# Phone Contact Rules
description: Per-phone-number allow and block rules for inbound calls and texts

---


# Phone Contact Rules

Per-phone-number allow/block rules for inbound calls and text messages. The phone number's `filter_mode` field decides how the rule list is interpreted:

- **`filter_mode: "whitelist"`** — only callers matching an `allow` rule can reach the number
- **`filter_mode: "blacklist"`** — every caller can reach the number except those matching a `block` rule

Set `filter_mode` on the phone number itself via `PATCH /numbers/{phone_number_id}` — see [Phone numbers](/docs/api/phone/numbers). Rules match on exact E.164 phone numbers only in v1 (`match_type: "exact_number"`); the field is wired in to stay forward-compatible when additional match types are added.

A rule with `status: "paused"` reserves the target slot without taking effect, so you can stage policy changes without losing the uniqueness claim.

**Auth.** List, get, and create accept admin API keys, claimed agent keys, and Clerk JWT; unclaimed (mid-signup) agent keys are rejected. `PATCH`, `DELETE`, and the org-wide list are admin + JWT only.

---

## List contact rules `GET`


List contact rules for a phone number, newest first.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `phone_number_id` | UUID | Phone number ID |

### Query parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `action` | string | — | Filter by `"allow"` or `"block"` |
| `match_type` | string | — | Filter by match type (`"exact_number"` is the only value in v1) |
| `limit` | integer | 50 | 1–200 |
| `offset` | integer | 0 | Offset for pagination |

### Response (200)

```json
[
    {
      "id": "r1a2b3c4-d5e6-7890-abcd-ef1234567890",
      "phone_number_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "action": "block",
      "match_type": "exact_number",
      "match_target": "+15551234567",
      "status": "active",
      "created_at": "2026-04-21T12:30:00Z",
      "updated_at": "2026-04-21T12:30:00Z"
    }
]
```

### Code examples

**cURL**

```bash
curl -X GET "https://inkbox.ai/api/v1/phone/numbers/PHONE_NUMBER_ID/contact-rules" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const response = await fetch(
    `https://inkbox.ai/api/v1/phone/numbers/${phoneNumberId}/contact-rules`,
    { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const rules = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    f"https://inkbox.ai/api/v1/phone/numbers/{phone_number_id}/contact-rules",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
rules = response.json()
```

---

## Create contact rule `POST`


Create an allow or block rule on a phone number.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `phone_number_id` | UUID | Phone number ID |

### Request body

| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `action` | string | Yes | `"allow"` or `"block"` |
| `match_type` | string | No | `"exact_number"` (default, the only value in v1) |
| `match_target` | string | Yes | E.164 phone number (e.g. `+15551234567`) |

New rules always start with `status: "active"` — to pause a rule use [Update contact rule](#update-contact-rule).

### Request example

```json
{
    "action": "block",
    "match_type": "exact_number",
    "match_target": "+15551234567"
}
```

### Response (201)

Returns the created rule.

### Error responses

| Status | Description |
| :--- | :--- |
| 409 | A non-deleted rule with the same `(match_type, match_target)` already exists. Response body contains `existing_rule_id`. |
| 422 | `match_target` is not a valid E.164 phone number |

### Code examples

**cURL**

```bash
curl -X POST "https://inkbox.ai/api/v1/phone/numbers/PHONE_NUMBER_ID/contact-rules" \\
    -H "X-API-Key: YOUR_API_KEY" \\
    -H "Content-Type: application/json" \\
    -d '{"action": "block", "match_type": "exact_number", "match_target": "+15551234567"}'
```

**JavaScript**

```javascript
const response = await fetch(
    `https://inkbox.ai/api/v1/phone/numbers/${phoneNumberId}/contact-rules`,
    {
        method: "POST",
        headers: {
            "X-API-Key": "YOUR_API_KEY",
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            action: "block",
            match_type: "exact_number",
            match_target: "+15551234567",
        }),
    }
);
const rule = await response.json();
```

**Python**

```python
import requests

response = requests.post(
    f"https://inkbox.ai/api/v1/phone/numbers/{phone_number_id}/contact-rules",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "action": "block",
        "match_type": "exact_number",
        "match_target": "+15551234567",
    },
)
rule = response.json()
```

---

## Get contact rule `GET`


Fetch a single contact rule by ID.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `phone_number_id` | UUID | Phone number ID |
| `rule_id` | UUID | Rule ID |

### Code examples

**cURL**

```bash
curl -X GET "https://inkbox.ai/api/v1/phone/numbers/PHONE_NUMBER_ID/contact-rules/RULE_ID" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const response = await fetch(
    `https://inkbox.ai/api/v1/phone/numbers/${phoneNumberId}/contact-rules/${ruleId}`,
    { headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const rule = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    f"https://inkbox.ai/api/v1/phone/numbers/{phone_number_id}/contact-rules/{rule_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
rule = response.json()
```

---

## Update contact rule `PATCH`


Update a rule's `action` or `status`.

> **Auth:** admin API key or Clerk JWT only.

`match_type` and `match_target` are immutable — delete the rule and create a new one to change the target.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `phone_number_id` | UUID | Phone number ID |
| `rule_id` | UUID | Rule ID |

### Request body

At least one of:

| Field | Type | Description |
| :--- | :--- | :--- |
| `action` | string | `"allow"` or `"block"` |
| `status` | string | `"active"` or `"paused"` (only these two values are accepted on PATCH; use DELETE to remove a rule) |

Sending `null` for either field is a client error (422) — omit the field to leave it unchanged.

### Code examples

**cURL**

```bash
curl -X PATCH "https://inkbox.ai/api/v1/phone/numbers/PHONE_NUMBER_ID/contact-rules/RULE_ID" \\
    -H "X-API-Key: YOUR_API_KEY" \\
    -H "Content-Type: application/json" \\
    -d '{"status": "paused"}'
```

**JavaScript**

```javascript
const response = await fetch(
    `https://inkbox.ai/api/v1/phone/numbers/${phoneNumberId}/contact-rules/${ruleId}`,
    {
        method: "PATCH",
        headers: {
            "X-API-Key": "YOUR_API_KEY",
            "Content-Type": "application/json",
        },
        body: JSON.stringify({ status: "paused" }),
    }
);
const rule = await response.json();
```

**Python**

```python
import requests

response = requests.patch(
    f"https://inkbox.ai/api/v1/phone/numbers/{phone_number_id}/contact-rules/{rule_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={"status": "paused"},
)
rule = response.json()
```

---

## Delete contact rule `DELETE`


Delete a contact rule. Returns `204 No Content` on success.

> **Auth:** admin API key or Clerk JWT only.

### Path parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `phone_number_id` | UUID | Phone number ID |
| `rule_id` | UUID | Rule ID |

### Code examples

**cURL**

```bash
curl -X DELETE "https://inkbox.ai/api/v1/phone/numbers/PHONE_NUMBER_ID/contact-rules/RULE_ID" \\
    -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
await fetch(
    `https://inkbox.ai/api/v1/phone/numbers/${phoneNumberId}/contact-rules/${ruleId}`,
    {
        method: "DELETE",
        headers: { "X-API-Key": "YOUR_API_KEY" },
    }
);
```

**Python**

```python
import requests

requests.delete(
    f"https://inkbox.ai/api/v1/phone/numbers/{phone_number_id}/contact-rules/{rule_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
```

---

## List org phone contact rules `GET`


Org-wide aggregate list of phone contact rules across every phone number the caller can see. Intended for admin dashboards that render rules org-wide without fanning out one per-number request per number.

> **Auth:** admin API key or Clerk JWT only.

Results are ordered `created_at` descending, with `id` as a stable tiebreaker so pagination stays consistent when rules from different numbers share a microsecond.

### Query parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `phone_number_id` | UUID | — | Narrow to a single phone number; omit to list across every number in the org |
| `action` | string | — | Filter by `"allow"` or `"block"` |
| `match_type` | string | — | Filter by match type (`"exact_number"` is the only value in v1) |
| `limit` | integer | 50 | Max rules (1–200) |
| `offset` | integer | 0 | Offset for pagination |

### Response (200)

Returns an array of [contact rule objects](#contact-rule-object) — same shape as the per-number list.

### Code examples

**cURL**

```bash
curl -X GET "https://inkbox.ai/api/v1/phone/contact-rules?action=block&limit=100" \\
    -H "X-API-Key: YOUR_ADMIN_API_KEY"
```

**JavaScript**

```javascript
const response = await fetch(
    "https://inkbox.ai/api/v1/phone/contact-rules?action=block&limit=100",
    { headers: { "X-API-Key": "YOUR_ADMIN_API_KEY" } }
);
const rules = await response.json();
```

**Python**

```python
import requests

response = requests.get(
    "https://inkbox.ai/api/v1/phone/contact-rules",
    headers={"X-API-Key": "YOUR_ADMIN_API_KEY"},
    params={"action": "block", "limit": 100},
)
rules = response.json()
```

---

## Contact rule object

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | UUID | Unique rule identifier |
| `phone_number_id` | UUID | Owning phone number |
| `action` | string | `"allow"` or `"block"` |
| `match_type` | string | `"exact_number"` (v1) |
| `match_target` | string | E.164 phone number |
| `status` | string | `"active"`, `"paused"`, or `"deleted"` |
| `created_at` | string | Creation timestamp (ISO 8601) |
| `updated_at` | string | Last-updated timestamp (ISO 8601) |

## Additional resources

- [Filtering guide](/docs/capabilities/filtering) — narrative walk-through of whitelist/blacklist semantics across mail and phone
- [Phone numbers](/docs/api/phone/numbers) — includes the `filter_mode` field that interprets these rules
- [Mail contact rules](/docs/api/mail/contact-rules) — the mail-side equivalent
