Errors & Rate Limits¶
How errors are returned¶
The API reports application errors inside the JSON body, with HTTP status 200. The code field is 0 on success and a non-zero integer on error; message explains the problem and data is an empty object.
{
"code": 40001,
"message": "Parameter 'advertiser_id' is required.",
"request_id": "13a3588ce1804d19b07f",
"data": {}
}
Your client must therefore:
- Parse the body as JSON on every response, regardless of HTTP status.
- Treat
code != 0as a failure, and branch on the code. - Log
request_idwith the failure.
There are two cases where the HTTP status is not 200, and both still use the envelope with code 40000: an unknown route returns HTTP 404, and a wrong HTTP method (for example POST on a report endpoint) returns HTTP 405. All endpoints are GET.
Error codes¶
code |
Meaning | Typical cause | What to do |
|---|---|---|---|
0 |
Success | — | Read data. |
40000 |
Route not found / method not allowed | Typo in the path, missing /open_api/v1.3 prefix, or a path that does not exist (HTTP 404); or a non-GET method such as POST (HTTP 405). Also check the trailing slash: a path without it is redirected (HTTP 307), which curl does not follow without -L. |
Fix the URL or use GET. Not retryable. |
40001 |
Parameter error | Missing required parameter, list parameter not JSON-encoded, unsupported dimension/metric/field/filter key, bad date, page_size out of range. |
Read message, fix the request. Not retryable. |
40002 |
Advertiser not authorized | advertiser_id (or an entry of advertiser_ids) is not one of the accounts returned by /oauth2/advertiser/get/ for your token. |
Use an id from the advertiser list. Not retryable. |
40100 |
Rate limit exceeded | More than 60 requests in the last 60 seconds with this token. | Wait the number of seconds in message (up to 60), then retry the same request. |
40105 |
Invalid or missing access token | Access-Token header absent, or the token is not recognized. |
Fix the token. Not retryable. |
Examples¶
40000 — route not found (HTTP 404):
{
"code": 40000,
"message": "Route not found. Check the path and the trailing slash.",
"request_id": "e3d3caebcb2d44669d18",
"data": {}
}
40000 — wrong HTTP method (HTTP 405):
{
"code": 40000,
"message": "Method POST is not allowed on this route; use GET.",
"request_id": "dc78585eac834bd9934c",
"data": {}
}
40001 — parameter error. The message always names the parameter and, where possible, lists the accepted values:
{
"code": 40001,
"message": "Parameter 'advertiser_ids' must be a JSON-encoded list.",
"request_id": "919e09a35abd4a098fba",
"data": {}
}
{
"code": 40001,
"message": "Unsupported filtering key 'campaign_id'. Supported: campaign_ids, campaign_name, objective_type, secondary_status",
"request_id": "c35957b3c24640ba9975",
"data": {}
}
{
"code": 40001,
"message": "page_size must be between 1 and 1000.",
"request_id": "7812da62495245e1a11d",
"data": {}
}
40002 — advertiser not authorized:
{
"code": 40002,
"message": "Advertiser 1234567890 is not authorized for this access token.",
"request_id": "93c00768e7db4c84beea",
"data": {}
}
40100 — rate limit:
{
"code": 40100,
"message": "Too many requests. Please retry after 60 seconds.",
"request_id": "c7b7cdd38ed54431a6fc",
"data": {}
}
40105 — token problems:
{
"code": 40105,
"message": "Access token is missing. Pass it in the Access-Token header.",
"request_id": "650da4d05e01495cbd04",
"data": {}
}
{
"code": 40105,
"message": "Access token is incorrect or has expired.",
"request_id": "431ccfb3a0ca43c6b6b2",
"data": {}
}
Common parameter mistakes¶
| Mistake | Result |
|---|---|
dimensions=ad_id,stat_time_day (comma list instead of JSON) |
40001 Parameter 'dimensions' must be a JSON-encoded list, got: ad_id,stat_time_day |
Forgetting to URL-encode the JSON (curl without --data-urlencode) |
Usually a 40001 saying the parameter must be a JSON-encoded list, because the brackets or quotes were mangled. Use curl -G --data-urlencode, or let your HTTP library encode params. |
Using the Reporting filtering list on /campaign/get/ |
40001 Parameter 'filtering' must be a JSON-encoded dict. |
Using the entity filtering object on /report/integrated/get/ |
40001 Parameter 'filtering' must be a JSON-encoded list. |
Singular key campaign_id in filtering |
40001, message lists the plural keys. |
data_level=AUCTION_AD with dimensions=["stat_time_day"] |
40001 dimensions must include ad_id when data_level=AUCTION_AD. |
Metric name installs or cost |
40001 Unsupported metric 'installs'. — use conversion/app_install and spend. |
Date 10/29/2026 |
40001 start_date and end_date must use the format YYYY-MM-DD. |
page=0 or non-integer |
40001 page must be >= 1. / page and page_size must be integers. |
Rate limits¶
- 60 requests per 60 seconds per access token, counted over a sliding window and shared across all endpoints. The limit is per token, not per advertiser: pulling 10 accounts shares the same budget.
- The request that exceeds the limit is not executed. It returns HTTP
200,code40100and a message of the formToo many requests. Please retry after N seconds.whereNis the number of seconds until the oldest request leaves the window (at most 60). There is noRetry-Afterheader; read the number frommessageor simply wait 60 seconds. - Rejected requests do not count against the window, so waiting the indicated time and retrying always succeeds.
Budgeting a daily pull¶
A full daily pull of one account at ad level is about 4 calls (/oauth2/advertiser/get/, /campaign/get/, /adgroup/get/, /ad/get/) plus one report call per page. With page_size=1000, re-pulling the last 3 days for all 10 accounts fits comfortably in a single minute. If you pull one day per request or use small page sizes you will hit the limit; prefer page_size=1000 and multi-day date ranges.
Retry rules¶
code |
Retry? |
|---|---|
40100 |
Yes — sleep the number of seconds in message (or 60), then resend the identical request. |
40000, 40001, 40002, 40105 |
No — the request is wrong; fix it. Retrying returns the same error and consumes rate-limit budget. |
| Network error / HTTP 5xx | Yes — these are transport failures, not API responses. Retry with back-off. |
Request ids¶
Every response carries a request_id, both in the JSON body and in the x-request-id response header. It is unique per request and is the fastest way to trace a problem on the server side. Include it when you ask for help.