IP Whitelisting
You can restrict an API application so that it only accepts requests from addresses you nominate. This limits the damage if your API key and secret are ever leaked: a stolen credential is useless from an address you have not allowed.
How it works
Each API application has its own list of allowed addresses.
| List | Behaviour |
|---|---|
| Empty | No restriction. The application accepts requests from any address. |
| One or more entries | Only those addresses may use the application. Everything else is rejected. |
The list is opt-in, so an existing integration keeps working until you add the first entry. Adding that first entry is the moment the application starts rejecting anything else, so add your production address before you add anything narrower.
The check happens after your key and secret are verified, so a request from a disallowed address is rejected whether or not the credentials were valid.
What you can list
Single addresses, or CIDR ranges, in IPv4 or IPv6:
41.90.1.2 a single IPv4 address
41.90.1.0/24 an IPv4 range (41.90.1.0 – 41.90.1.255)
2001:db8::1 a single IPv6 address
2001:db8::/32 an IPv6 range
A range is useful when your servers sit behind a NAT gateway or auto-scale across several addresses.
Rejected requests
A request from an address that is not allowed returns 403:
{
"success": false,
"message": "Requests from 8.8.8.8 are not allowed for this application.",
"error": "IP_NOT_ALLOWED",
"data": null
}
The address shown is the one the platform actually saw. That is the useful part of the message: if it is not the address you expected, your traffic is leaving through a NAT gateway, a proxy, or a different egress address than you thought, and that is what needs to be on the list.
Warning
Nothing is sent and nothing is charged when a request is rejected this way.
Finding your address
The simplest check is to make a request and read the address back out of the error above. Otherwise, from the server that will call the API:
curl -s https://api.ipify.org
Run it on the machine that makes the API calls, not your laptop — they are rarely the same address.
Blocked requests are recorded
When a request is refused, the address it came from is recorded against the application and shown in the portal for review, with how many times it has tried and when it last did.
Each one can be:
- Approved — the address is added to the allowed list, and calls from it succeed from then on.
- Denied — the decision is recorded and the address stays blocked. It stops appearing for review, and further calls from it update its counter without bringing it back.
This is the quickest way to add a legitimate address you had not accounted for: make the call, then approve the address the platform actually saw. It also means an unexpected address using your credentials is visible rather than only appearing in a log.
Two details worth knowing:
- Nothing is recorded while an application is unrestricted, because nothing is refused. The list only fills once there is at least one allowed entry.
- Repeat attempts from the same address within a few seconds are counted loosely rather than exactly, so a client retrying in a tight loop shows a lower total than the number of requests it made.
Managing the list
Allowed addresses are managed from the portal, under the API application's settings. You can add an address with an optional label — "Nairobi office", "AWS NAT gateway" — so it is clear later why each entry exists.
Two things the portal will tell you, because both change who can call the API:
- adding the first entry switches the application from unrestricted to restricted;
- removing the last entry returns it to accepting calls from anywhere.
If you lock yourself out
Remove the entries from the portal, which is session-authenticated and not subject to the API allowlist. The restriction only applies to the SMS API, so losing access to it never locks you out of your account.
A note for self-hosted deployments
If the platform runs behind a load balancer, nginx, or a CDN, it must be configured to trust those proxies before whitelisting is used — otherwise the address it sees is the proxy's, not the caller's, and no allowlist can match. Your platform operator will have handled this; it is mentioned here because it is the usual reason a correctly configured allowlist appears to reject everything.