Skip to content

Rate limits

Rate limits protect the service and your balance from runaway loops. They are counted in requests per minute, separately from credits.

Caller Limit
sk_live_ key The key’s own limit, shown in the dashboard
pk_ key The key’s own limit, counted per visitor IP, and the key’s overall limit
Client token (ct_) The limit of the key that created it, shared with that key and all its other tokens
sk_test_ keys 10 requests per minute and a daily quota of 100 per UTC day counted in credits, shared by the organization
demo 10 requests per minute per IP
GET /v1/places/search An extra 30 requests per minute per key or token, on top of the above

Limits work as a token bucket: a key with a limit of 120 can burst up to 120 requests, and capacity refills continuously at 120 per minute.

Successful and rate-limited responses carry the IETF RateLimit headers for the bucket that applied:

Header Meaning
ratelimit-limit Requests per minute for this bucket
ratelimit-remaining Requests you can make right now
ratelimit-reset Seconds until the bucket is full again

The API returns 429 with code: "rate_limited" and a Retry-After header in seconds. Nothing is charged.

HTTP/1.1 429 Too Many Requests
Retry-After: 5
ratelimit-limit: 10
ratelimit-remaining: 0
ratelimit-reset: 59
{
"type": "https://navapatra.com/docs/errors#rate_limited",
"title": "Too many requests",
"status": 429,
"detail": "Rate limit exceeded. Retry in 5 s.",
"code": "rate_limited",
"requestId": "7b02b780-7584-4888-b40f-0d701653609e"
}

When a test key passes 100 requests in a day, the detail says so and Retry-After points to the next UTC midnight.

Wait for Retry-After, then retry. For bulk jobs, pace requests below the limit instead of relying on retries:

async function call(url: string, init: RequestInit, attempts = 3): Promise<Response> {
for (let i = 0; ; i++) {
const res = await fetch(url, init);
if (res.status !== 429 || i >= attempts - 1) return res;
const wait = Number(res.headers.get('retry-after') ?? '1');
await new Promise((r) => setTimeout(r, Math.min(wait, 60) * 1000));
}
}

The TypeScript SDK does this for you. For many guna milan scores, use batch matching: 100 pairs in one request count once against the rate limit.

Need a higher limit? Write to hello@navapatra.com with your expected volume.