Docs
Rate limits
A request limit per project environment that follows your plan, a limit per end user for apps, and fixed caps on the test environment.
Requests per project
Your secret keys may make this many requests together in every 10-second window. The limit follows the plan of the project and applies to both live and test keys of that project.
| Plan | Requests per 10 seconds, per project environment |
|---|---|
| Test (free) | 100 |
| Starter | 300 |
| Growth | 1,000 |
| Scale | 10,000 |
The limit is shared by all secret keys of a project environment (live and test count apart), so adding keys does not raise it; end-user client tokens are limited separately (below). Beyond a limit the API answers 429 with Retry-After.
Treat the limit as a guide for pacing, not as a quota you can use exactly. A plan change reaches your keys within about 30 seconds.
Other limits
- Client tokens: 100 requests per 10 seconds per end user, so one busy user cannot use up your app's allowance; and at most 200 new receiver ids an hour per end user (
429,details.limit: "new_receivers_per_hour"). - Failed authentication: requests with a missing, unknown, revoked or expired key or client token count against a separate guard per IP address. Valid keys and tokens never count against it, so many servers or app users behind one IP are not limited by it.
- Receipt verification: 20 per 10 seconds per project and environment (Receipt validation).
- Body size: 16 KB.
These are request limits, not usage quotas: the API does not meter or bill requests.
The 429 response
HTTP/1.1 429
Retry-After: 10
{ "error": { "type": "rate_limited", "message": "Too many requests. Slow down and retry.",
"request_id": "req_…", "retryable": true } }
Retry-After is in seconds. Responses carry no other rate-limit headers, so count
your own requests if you need to stay under the limit.
Backing off
Retry 429 and 5xx after the Retry-After delay (or an
exponential delay if there is none), with a little jitter, and reuse the same
Idempotency-Key so a request that did go through is not repeated.
export async function withBackoff(send, { maxAttempts = 5 } = {}) {
for (let attempt = 1; ; attempt++) {
const res = await send();
if (res.status !== 429 && res.status < 500) return res;
if (attempt >= maxAttempts) return res;
const retryAfter = Number(res.headers.get("Retry-After"));
const waitMs = (retryAfter > 0 ? retryAfter * 1000 : 2 ** attempt * 250) + Math.random() * 250;
await new Promise((r) => setTimeout(r, waitMs));
}
}
Test environment limits
The test environment is for building and trying, not for running an app. On every plan a test ledger allows:
- 50 users (active plus deleted since the last reset; receivers count too).
- 5,000 operations per UTC month. An operation is a successful credit, debit, gift send or gift reversal. A replay of the same
Idempotency-Keyis not counted.
Past a cap, those writes fail with 403 test_limit_reached (details.limit
is users or monthly_operations, and details.max the cap).
It is not retryable. Catalog edits, token creation and user deletion are never refused.
"Reset test data" in the dashboard wipes the test users and frees the user cap, but does not lower
the month's operation count. Live environments have no such caps. Test gift rooms hold up to 20
viewers.
Questions or something unclear? support@giftingstack.com.