# Change one or more rules of the SMS policy

`PUT /api/v1/phone/policy`

- Authentication: Secret API key as a bearer token
- Billing: Free.
- Group: Phone

Names only the rules that change; the rest stay as they were, and the change applies to the account's next lookup. `max_risk_score: null` ignores the score, `block_signals: []` blocks on no signal, `allowed_countries: null` sends to any country and `blocked_countries: null` blocks none. Country codes are read upper-case and kept sorted; an empty `allowed_countries` is refused, because it would block every number.

A country allow-list is the first control against SMS pumping to destinations the business never serves. It is a business choice about where to send, not a verdict that a country's numbers are fraudulent. The country is the number's own, read from its calling code and prefix, so +1 876 is Jamaica rather than the United States; a number with no country (international networks, global freephone) is outside every allow-list.

`blocked_line_types` refuses the line types named; `fixed_line_or_mobile` can never be one, because it is what the numbering plan answers when it cannot tell a mobile from a landline, which is most of North America. UK 084 and 087 numbers answer `shared_cost`, not `premium_rate`, so a sender that refuses them lists both. `require_reachable: true` passes only a lookup that asked for the live check (`hlr`) and got `reachable: true`: a handset the network could not reach is blocked as `unreachable`, and a lookup with no live answer as `unconfirmed` — while the live check is not enabled on the service, that is every lookup.

`block_opted_out` (default true) blocks every lookup of one number — the single lookup, the browser endpoint, the dashboard, the MCP tool and the consistency check — when your own suppression list (that of the user whose key or session made the lookup; each member keeps their own, while the policy is the account's) holds the number as opted out (`meta.opted_out: true`), as `blocked_by: opted_out`, checked right after `invalid`. Batch, bulk and monitor runs serve such a number from the list as `suppressed` either way, and test numbers never read the list. An OTP or transactional sender may want it off: an opt-out from marketing does not always forbid a verification code, and the person typing the number may be its owner asking for one again. Off, the number is decided like any other and `meta.opted_out` still reports it. Honouring an opt-out stays the account's obligation; the rule is not a consent record.

A body naming none of the seven rules is refused with a 422 keyed `policy`, because that is the shape a misspelled key takes.

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `max_risk_score` | integer | null | no | Block when risk_score is above this; null ignores the score. |
| `block_signals` | string[] | null | no | Signals that block whenever they fire, whatever the score. |
| `allowed_countries` | string[] | null | no | Send only to numbers of these regions (ISO 3166-1 alpha-2, as the numbering plan knows them); null sends to any. |
| `blocked_countries` | string[] | null | no | Never send to numbers of these regions; null or an empty list blocks none. |
| `blocked_line_types` | string[] | null | no | Line types that block. fixed_line_or_mobile can never be blocked. |
| `require_reachable` | boolean | no | Block unless a live check reached the handset (hlr_checked true and reachable true). |
| `block_opted_out` | boolean | no | Block a single or browser lookup of a number your suppression list holds as opted out (meta.opted_out true), as blocked_by opted_out. True by default; an OTP or transactional sender may switch it off. Batch, bulk and monitor runs answer such a number suppressed either way. |

## Example request

```bash
curl -X PUT https://spaw.co/api/v1/phone/policy \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
  "max_risk_score": 50,
  "allowed_countries": [
    "GB",
    "IE"
  ]
}'
```

## Responses

### 200 — The policy now in force.

## Error codes

- `UNAUTHENTICATED` — https://spaw.co/docs/errors/UNAUTHENTICATED
- `RATE_LIMITED` — https://spaw.co/docs/errors/RATE_LIMITED
- `VALIDATION_FAILED` — https://spaw.co/docs/errors/VALIDATION_FAILED

---

Canonical page: https://spaw.co/docs/api/update-phone-policy · OpenAPI document: https://spaw.co/openapi.json · All endpoints: https://spaw.co/docs/api
