Fraud caps
Fraud caps are your account’s anti-abuse limits. Each outbound send runs against two thresholds: a per-minute velocity cap (how fast) and a daily-spend cap in cents (how much). When a cap trips, the send is rejected — which is exactly what you want when something on your side, or an attacker on theirs, starts generating anomalous traffic. The platform sets floors — conservative defaults per channel — that apply even with no override configured. This page shows how to read the floors, tighten a channel below its floor as a wallet guard, and size a cap for a real workload. The endpoint isGET / PUT /api/v1/settings/compliance/fraud-caps. Reads are open to
any authenticated member of your organization; writes are restricted
to owners. Full request shapes are in the
settings API reference.
What a fraud cap is — and is not
A fraud cap is an abuse control, not a throughput control. Too-low per-minute limits generate429 rejections; too-high limits let a leak
or a toll-fraud attack run up spend before anyone notices. Two
different knobs answer those questions on this platform — don’t
conflate them:
Raise your envelope with
Channel rate overrides only after
sizing the fraud guard here. A send must pass both gates.
Reading floors and overrides
GET /api/v1/settings/compliance/fraud-caps returns one object with
two blocks:
channels— one entry per covered channel (sms,mms,whatsapp,rcs,viber,email,telegram,push,web_chat,messenger,line,instagram,fax,apple_messages). Each entry carriesmax_per_minandmax_daily_spend_cents— your override, ornullwhen the floor applies — plusfloor_per_minandfloor_daily_spend_centsfrom the platform.voice— the envelope for outbound calls:max_calls_per_min,max_daily_spend_cents, a per-destination-countrycountry_max_per_minmap (see below), and the voice floors.
max_per_min: null on a
channel means “floor applies,” not “unlimited.”
If the settings lookup fails transiently, the response degrades to
floors-only (all overrides null) rather than a 5xx. The dashboard
panel still renders, and enforcement keeps using the floors — a read
error never widens your exposure.
Writing overrides
PUT /api/v1/settings/compliance/fraud-caps is owner-only. The
body carries two optional blocks, and both are sparse: only
channels you include are touched — everything else keeps its stored
value. Inside a channel entry, a null leaf clears just that override
and reverts to the floor.
null) is safe — it widens back to the platform guard, never
to “no guard.” To restore a whole channel’s defaults, clear both
leaves and omit nothing else:
422 on the write means a leaf was non-integer,
non-positive, or above that ceiling — fix the payload and retry.
The voice.country_max_per_min map is replaced wholesale on every PUT
that includes it: send the entire map you want active. An empty map
clears all per-country caps.
voice.max_calls_per_min caps the overall outbound dial rate, while
voice.country_max_per_min clamps one named ISO country
independently. On voice, 0 is a legal value: a country’s mid-attack
“stop dialing this destination” lever that doesn’t exist on the
messaging channels.How voice fraud interacts with auto-blocks
Per-country caps are one of three voice-side layers you should understand together:- Platform floors — always-on per-tenant and per-country call-rate guards, plus a curated premium-rate prefix blocklist.
- Your overrides — the
voiceblock above: overall velocity, daily spend, and per-country rates you tighten below the floors. - Automatic per-destination blocks — when a detector sweep sees traffic-pumping (IRSF revenue-share) or a Wangiri callback burst concentrated on one specific number, it applies a reversible, self-expiring block on exactly that destination. Legitimate calls to every other number are unaffected.
0) while the anomaly is investigated. Full coverage of the
auto-block categories, lifetimes, and read endpoints is in
Voice destination auto-blocks.
Worked sizing examples
US toll-free SMS, a marketing dispatcher
A mid-size sender runs a campaign that delivers about 1,200 SMS per minute on peak days, with a verified sender registration. The account has never had a fraud incident, but an operator wants damage-bound limits in case a queue duplicates jobs or a token leaks.- Velocity.
1,200 / 60 = 20sends per second. Leave headroom for bursts: setsms.max_per_minto the sustained peak —1200— not the average. - Spend. At 648/hr
. A daily budget of roughly 8 peak hours is500000cents ($5,000). Setsms.max_daily_spend_cents` there — the first anomalous spike that runs past a working day cuts itself off. - Verify.
PUTthe map, thenGETthe endpoint:smsshows your values inmax_per_minandmax_daily_spend_cents, and the floors appear alongside (so you can see the delta you introduced). Run a batch against the cap — at 20+ msg/sec you’ll see the floor of rejections stop exactly at the limit you chose, while a second run under the cap completes cleanly.
Voice IVR campaign, outbound customer callbacks
A utility dials opted-in customers for payment reminders from an IVR-driven dialer: about 25 concurrent legs at any moment, only US destinations, ~$40/day in voice spend.- Overall rate. Set
voice.max_calls_per_minto30— a hair above the observed 25/minute peaks — so a wedged dialer loop rejecting-retrying can’t sustain a spike. - Country clamp. Cap
voice.country_max_per_minon the one destination country the campaign touches (US: 12) so a misrouted campaign to a premium-tier destination is cut at the source. - Spend. Set
voice.max_daily_spend_centsto6000($60) — 1.5× the normal daily bill, so anomalies still stop but a busy Monday doesn’t stall.
Audit trail and verification
EveryPUT writes an entry to your audit log naming the capped keys —
the resulting override map and the cleared list — so a raised or
cleared guard is part of the trail, not a silent change. Owners verify
a change in three steps, the same loop as on
channel-rate-overrides:
- Set.
PUTthe overrides (owner role). - Read back.
GETthe endpoint and confirm each field carries your values; cleared leaves shownull(floor applies). - Confirm on the send path. Send on the capped channel at your historic rate and watch rejections stop at the new boundary — previously the same burst only stopped at the platform floor.