Skip to content

API reference/phone

Change one or more rules of the SMS policy

PUT/api/v1/phone/policy

authentication
Secret API key as a bearer token
billing
Free.

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 description
max_risk_scoreinteger | nullBlock when risk_score is above this; null ignores the score.
block_signalsstring[] | nullSignals that block whenever they fire, whatever the score.
allowed_countriesstring[] | nullSend only to numbers of these regions (ISO 3166-1 alpha-2, as the numbering plan knows them); null sends to any.
blocked_countriesstring[] | nullNever send to numbers of these regions; null or an empty list blocks none.
blocked_line_typesstring[] | nullLine types that block. fixed_line_or_mobile can never be blocked.
require_reachablebooleanBlock unless a live check reached the handset (hlr_checked true and reachable true).
block_opted_outbooleanBlock 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

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"
  ]
}'
const response = await fetch('https://spaw.co/api/v1/phone/policy', {
  method: 'PUT',
  headers: {
    'Authorization': 'Bearer sk_live_…',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    "max_risk_score": 50,
    "allowed_countries": [
      "GB",
      "IE"
    ]
  }),
});
const result = await response.json();
import requests

response = requests.put(
    'https://spaw.co/api/v1/phone/policy',
    headers={'Authorization': 'Bearer sk_live_…'},
    json={
        'max_risk_score': 50,
        'allowed_countries': [
            'GB',
            'IE'
        ]
    },
)
result = response.json()
$ch = curl_init('https://spaw.co/api/v1/phone/policy');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST => 'PUT',
    CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_live_…', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'max_risk_score' => 50,
        'allowed_countries' => [
            'GB',
            'IE'
        ]
    ]),
]);
$result = json_decode(curl_exec($ch), true);
from spaw import Client

client = Client('sk_live_…')
result = client.update_phone_policy(max_risk_score=50, allowed_countries=[
    'GB',
    'IE'
])
import Spaw from 'spaw';

const spaw = new Spaw({ apiKey: 'sk_live_…' });
const result = await spaw.updatePhonePolicy({
    maxRiskScore: 50,
    allowedCountries: [
        'GB',
        'IE'
    ]
});
use Spaw\Client;

$spaw = new Client('sk_live_…');
$result = $spaw->updatePhonePolicy([
    'max_risk_score' => 50,
    'allowed_countries' => [
        'GB',
        'IE'
    ]
]);

This endpoint has no console on its page. It writes to your account. A documentation page can show you the request; making the change is for the dashboard or for a call you make yourself.

Responses

200The policy now in force.

Error codes

Failures answer { success: false, error: { code, message, request_id } }. Each code has its own page.

markdown version·openapi.json