Getting started
Authentication
Every API request carries an API key from the portal. How to send it, what the gateway checks before accepting a request, rate limits, IP allow-lists and the errors each check produces.
API keys
Keys are created in the portal under Developer, API tab. Each key is a 64-character string tied to your account; you can hold several at once (one per system is a good habit), give each a name and an IP allow-list, and regenerate or delete any of them. The portal shows when a key was last used.
A key grants everything the account can do over the API: sending on every channel and reading balances. Treat it like a password: keep it on the server, never in a browser or a mobile app, and regenerate it if it leaks.
Sending the key
Put the key in a request header. X-API-Key is checked first and is the form every example in these docs uses.
# Recommended
X-API-Key: YOUR_API_KEY
# Also accepted
Authorization: Bearer YOUR_API_KEY
# Legacy: HTTP Basic with the key as the username and an empty password
Authorization: Basic base64("YOUR_API_KEY:")With Basic auth the gateway accepts the key on either side of the colon, so base64(":YOUR_API_KEY") works too. Leading and trailing whitespace around the key is trimmed.
What is checked
Before a request reaches an endpoint, the gateway checks, in this order:
- A key is present and matches a credential.
- The credential is enabled.
- The account it belongs to exists and is active.
- The credential has not passed its expiry date, if one was set.
- The caller's IP address is on the credential's allow-list, if one was set.
- The credential is under its requests-per-minute limit.
The first check that fails ends the request with HTTP 401 (or 429 for the rate limit) and a JSON body naming the reason. A request that passes all six is logged against that credential, so the portal can show which key sent what.
{
"message": "IP_NOT_ALLOWED",
"success": false,
"api_reference": "1764184470578998353"
}JSON on every endpoint
Authentication runs before the endpoint handler, so these errors are JSON even on the legacy XML endpoint. An XML client must be ready to receive a JSON body with a 401 or 429 status.
Rate limits
Each credential has a requests-per-minute limit, counted per calendar minute. The default is 60. Going over it answers 429 with RATE_LIMIT_EXCEEDED until the next minute starts; requests refused this way send nothing and cost nothing. The limit is set per credential by Unicom360; ask support if a system needs more. Note that it counts requests, not recipients: one request to 2,000 numbers is one request.
IP allow-list
When you add addresses to a credential's allow-list, only requests from those addresses are accepted; the rest get IP_NOT_ALLOWED. Add the public addresses your servers send from. An empty list allows any address, as does the literal *. Restricting a key to the addresses that actually use it is the single most effective protection against a leaked key.
Expiry and rotation
A credential can carry an expiry date, after which it answers CREDENTIAL_EXPIRED. To rotate a key without downtime, create a second credential, move your systems to it, then delete the old one. Regenerating a key in place replaces it immediately: anything still sending the old value fails from that moment.
Authentication errors
HTTP 401 (429 for the rate limit) with {"message": "<code>", "success": false, "api_reference": "..."}. JSON on every endpoint, including the XML one.
| message | Meaning |
|---|---|
| Missing API key. Provide X-API-Key header or Authorization: Bearer <api_key> | Neither header was present. |
| Invalid authorization format. Use 'Bearer <api_key>' or 'Basic <base64>' | The Authorization header used another scheme. |
| Invalid Basic auth format. Use api_key as username | Basic credentials decoded, but neither side of the colon held a key. |
| Invalid Base64 encoding in Basic auth | The Basic credentials were not valid base64. |
| AUTHENTICATION_FAILED | The key does not match any credential. |
| CREDENTIAL_DISABLED | The key exists but was switched off. |
| CLIENT_NOT_FOUND | The key is not attached to an account. Contact support. |
| CLIENT_DISABLED | Your account is suspended. Contact support. |
| CREDENTIAL_EXPIRED | The key's expiry date has passed. |
| IP_NOT_ALLOWED | The request came from an address outside the key's allow-list. |
| RATE_LIMIT_EXCEEDED | More requests this minute than the key allows (HTTP 429). Wait for the next minute. |
Missing API key. Provide X-API-Key header or Authorization: Bearer <api_key>
- Meaning
- Neither header was present.
Invalid authorization format. Use 'Bearer <api_key>' or 'Basic <base64>'
- Meaning
- The Authorization header used another scheme.
Invalid Basic auth format. Use api_key as username
- Meaning
- Basic credentials decoded, but neither side of the colon held a key.
Invalid Base64 encoding in Basic auth
- Meaning
- The Basic credentials were not valid base64.
AUTHENTICATION_FAILED
- Meaning
- The key does not match any credential.
CREDENTIAL_DISABLED
- Meaning
- The key exists but was switched off.
CLIENT_NOT_FOUND
- Meaning
- The key is not attached to an account. Contact support.
CLIENT_DISABLED
- Meaning
- Your account is suspended. Contact support.
CREDENTIAL_EXPIRED
- Meaning
- The key's expiry date has passed.
IP_NOT_ALLOWED
- Meaning
- The request came from an address outside the key's allow-list.
RATE_LIMIT_EXCEEDED
- Meaning
- More requests this minute than the key allows (HTTP 429). Wait for the next minute.
Every other error the gateway returns is listed on the Errors page.