Skip to content

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:

  1. Parse the body as JSON on every response, regardless of HTTP status.
  2. Treat code != 0 as a failure, and branch on the code.
  3. Log request_id with 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, code 40100 and a message of the form Too many requests. Please retry after N seconds. where N is the number of seconds until the oldest request leaves the window (at most 60). There is no Retry-After header; read the number from message or 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.