Dates are UTC
Every timestamp is UTC ISO 8601. Every daily value is adate string such as 2026-07-30, with no time and no offset, because the underlying column is a PostgreSQL date.
Today means the UTC date. An instance in Auckland and an instance in Los Angeles agree on which day a position belongs to, which is what makes histories comparable.
Do not localize a date string before comparing it. Parsing 2026-07-30 as local midnight and formatting it back can shift it by a day.
A date you send must exist on the calendar, and a window must run forwards. A day such as 2026-02-30 or a to that falls on an earlier UTC day than from answers 400 rather than another day’s data or an empty series. The MCP tools refuse the same inputs with a tool error.
Positions are 1 based and null is meaningful
Position 1 is the top result.null means the keyword was checked and the app was not found within that row’s depth, which defaults to 200.
Render null as a bound derived from the row’s own depth, such as >200. See Positions and rank depth.
Queued operations return 202
Anything that enqueues store work answers immediately with202 and a job reference rather than waiting for a result.
Poll the resource afterwards rather than expecting the response to carry the result. A
202 is not a promise that the job succeeded, only that it was accepted.
Scores are shown on a 0 to 100 scale
Traffic and difficulty are stored on a 0 to 10 scale with their provenance, and some responses return them on that stored scale. Volume and opportunity are always 0 to 100, and opportunity is computed per app on read and never persisted. See Which scale does a response use? before comparing numbers across endpoints. Apple and Google Play scores come from different public evidence and are not directly comparable. See Traffic, difficulty and opportunity.installs is a BigInt
installs exceeds the safe integer range in the database, so it is stored as a BigInt and serialized as a JSON number. A client reading it into a 64 bit integer type is fine. A client reading it into a JavaScript number is also fine at realistic install counts.
Country codes are two letters
A country is two lowercase letters such asus, gb or de, validated by shape rather than against a fixed list, so any live storefront works. Uppercase is rejected.
Country belongs to the keyword, not to the app, which is why so many endpoints take one. See Countries and markets.
Rate limits depend on how the instance is run
A self hosted instance applies no API rate limits beyond the authentication throttle. What is limited there is store collection, bySCRAPE_ITUNES_RPM and SCRAPE_GPLAY_RPM, so a script may read as often as it likes while queuing work has a real cost.
A metered instance limits requests per workspace and per plan, in three classes, and every response carries RateLimit headers. See Rate limits and quotas.
Either way, GET /jobs/budget returns the estimated daily fan out broken down by kind alongside your capacity, which is the right thing to check before adding keywords or markets programmatically. See The daily pipeline and rate limits.
Related
Error responses
What a failure looks like.
Rate limits and quotas
What a metered instance allows.