XML Feed Status & Errors
Two things are easy to conflate on this wire: a no-fill and a failure. A 204 is
not an error. It is the auction telling you nobody bid, and at any real volume
you will see a great many of them.
HTTP status codes
| Status | Meaning | What to do |
|---|---|---|
200 | A fill. Body carries one or more ads | Serve it, fire imp_url |
204 | No fill, empty body | Nothing, this is normal and expected |
400 | A parameter is missing or malformed | Fix the call, see the codes below |
401 | Unknown or revoked feed key | Check the key in the path |
403 | Supply type mismatch, or account suspended | Ask for the right key, or check your account |
410 | The ad you are notifying on has expired | Stop firing notices past exp |
429 | Above the provisioned request rate | Back off, and ask for a higher limit if it is sustained |
500 | Exchange error | Treat as a no-fill, do not retry the same call |
503 | Exchange shedding load | Treat as a no-fill, reduce rate briefly |
A healthy feed is mostly 200 and 204, with a 4xx rate under 1%. Anything
above that is a bug in the integration rather than a property of the traffic.
Error bodies
A 4xx carries a body naming what failed. It follows the format you asked for.
{
"error": {
"code": "MISSING_PARAM",
"message": "ua is required",
"rid": "8f2a1c30-6b4e-4d9a-9f11-2c7e3b5a8d40"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<error>
<code>MISSING_PARAM</code>
<message>ua is required</message>
<rid>8f2a1c30-6b4e-4d9a-9f11-2c7e3b5a8d40</rid>
</error>
Error codes
| Code | Status | Meaning |
|---|---|---|
MISSING_PARAM | 400 | A required parameter is absent. message names it. |
INVALID_IP | 400 | ip is not a routable IPv4 or IPv6 address. |
INVALID_UA | 400 | ua is empty, or was not URL-encoded. |
INVALID_SUBID | 400 | subid exceeds 64 characters or uses disallowed characters. |
INVALID_FORMAT | 400 | format is neither json nor xml. |
INVALID_SIZE | 400 | img_size or icon_size is not WxH. |
UNKNOWN_KEY | 401 | The feed key does not exist. |
KEY_REVOKED | 401 | The feed key was rotated or withdrawn. |
TYPE_MISMATCH | 403 | Parameters do not match the key's supply type. |
ACCOUNT_INACTIVE | 403 | Account suspended, or not yet enabled for production. |
AD_EXPIRED | 410 | The notice fired after exp. |
RATE_LIMITED | 429 | Above the provisioned rate for this key. |
rid is echoed on every error. Quote it in support requests, since we retain
full request and response bodies for seven days and can replay any call from that
window.
Rate limiting
429 carries a Retry-After header in seconds. Honour it. Requests sent inside
the window are not queued; they are counted against you and returned 429 again.
HTTP/1.1 429 Too Many Requests
Retry-After: 2
Content-Type: application/json
Rate is provisioned per feed key rather than per account, so a spike on one placement does not starve the others. If you are hitting the ceiling on real traffic rather than on a retry loop, ask the integration office for a raise.
Traffic quality holds
Separate from status codes, a feed can be throttled or paused on quality grounds.
You will see it as a rising 204 rate rather than as an error, and your
integration engineer will be in touch before it happens. The triggers, in the
order we hit them:
- Impression notices far below the number of ads requested, which usually means ads are being requested and not shown
- Billable clicks well below recorded clicks, sustained over a few days
- Traffic from datacentre ranges arriving with residential user agents
- A single
uidoripclicking at a rate no person achieves
None of these is fatal on its own, and all of them are easier to fix while the volume is small.
Next: SSP Report.