Rate limits and errors
Request limits for the panel API and the ad-serving endpoints, the status codes UluMob returns, and how to retry safely.
UluMob limits how fast clients can call the API and the ad server. Within the limits, errors follow a small set of status codes with JSON bodies, so a script can handle them in one place.
Panel API limits
These apply to https://ulumob.com/api/v1.
| Endpoint | Limit |
|---|---|
POST /auth/login, POST /auth/register |
5 a minute per email address and IP, and 30 a minute per IP |
POST /publisher/websites/{id}/verify |
6 a minute |
| Every other endpoint | 120 a minute per account |
The 120-a-minute limit is shared by all keys of the same account. Two scripts running with two keys draw from one allowance.
Ad server limits
The public engine endpoints on https://ulumob.com are limited per client IP address. Each limit has a sustained rate and a short burst allowance.
| Endpoint | Sustained | Burst |
|---|---|---|
/delivery |
50 a second | 200 |
/imp |
50 a second | 200 |
/click |
5 a second | 20 |
/postback |
100 a second | 500 |
Real visitors do not come near these numbers. If you send postbacks from your tracker in large batches, spread them out or keep within the burst.
Separately from rate limits, ad requests that come too fast from one address to one zone get no ad and are not charged. That is a quality check, not an error; see Traffic quality rules.
When you hit a limit
The response has status 429 and a Retry-After header with the number of seconds to wait.
HTTP/1.1 429 Too Many Requests
Retry-After: 2
On /postback the body also says so:
{"status": "rejected", "reason": "rate_limited"}
Wait at least the Retry-After time before the next attempt. A rate-limited postback is not recorded, so send it again.
Status codes
| Status | Meaning | What to do |
|---|---|---|
| 200 | Success | |
| 201 | Created (campaign, zone, website, key, deposit, payout request) | Store the returned id. |
| 204 | No ad available (/delivery in JSON mode) |
Show nothing, or your own fallback. |
| 401 | No token, or the token is invalid, expired or revoked | Check the Authorization header; create a new key if needed. |
| 403 | Your account lacks the role for this endpoint, or is not active | Use an account with the right role, or contact support. |
| 404 | The item does not exist or belongs to another account | Check the id. |
| 422 | The request was understood but refused | Read message and errors. |
| 429 | Rate limit reached | Wait for Retry-After. |
| 503 | A dependency is not available, for example card payments not yet configured | Try later. |
Items that belong to another account return 404, not 403, so ids cannot be probed.
Error bodies
Errors are JSON. Validation errors list each failing field:
{
"message": "Banner image must be exactly 300x250 and at most 150 KB.",
"errors": {
"ads.0.creative_id": ["Banner image must be exactly 300x250 and at most 150 KB."]
}
}
Fields inside arrays use dot paths, such as ads.0.destination_url or targeting.geos.values.2.
Business-rule refusals carry only a message, for example when deleting a creative that an ad still uses, or requesting a payout within 7 days of the last one.
Retrying safely
- Retry
429,503and network errors, with a growing pause between attempts. - Do not retry
401,403,404or422unchanged; the result will be the same. - For card deposits, always send the same
Idempotency-Keyheader when retrying. The server then returns the original deposit instead of creating a second one. See Deposits and receipts. - Postbacks are de-duplicated per click and conversion type within the attribution window (7 days by default), unless that conversion type allows repeats. A repeat answers
{"status":"ignored","reason":"duplicate"}.
Something missing or wrong? Tell us.