Skip to content

Rate limits

The partner API allows 300 requests per minute per app. The limit is counted per app — not per credential, per merchant or per source address — so an app serving fifty merchants shares one budget across all of them.

Every partner response carries the current state of your budget.

HeaderExampleMeaning
X-RateLimit-Limit300Requests allowed in the window
X-RateLimit-Remaining287Requests left in the current window
X-RateLimit-Reset1785312000Unix timestamp (seconds) when the window rolls over

The window is fixed, not sliding: the counter resets on the minute boundary, and unused budget does not carry over.

429 Too Many Requests
{
"status": "error",
"statusCode": 429,
"timestamp": "2026-07-29T09:41:00.052Z",
"path": "/v1/items",
"message": "Rate limit exceeded. Try again in 14 seconds.",
"code": "partner.rate_limited",
"correlationId": "5f0e2a71-7c34-4c50-9a2e-b3d1f8c60e29"
}

Wait for the reset rather than retrying immediately — a retry inside the same window is guaranteed to fail and burns budget you will want when the window turns over.

async function callPartner(request) {
for (let attempt = 0; attempt < 3; attempt++) {
const response = await fetch(request);
if (response.status !== 429) return response;
const reset = Number(response.headers.get('X-RateLimit-Reset') ?? 0) * 1000;
const waitMs = Math.max(reset - Date.now(), 1000) + Math.random() * 250;
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
throw new Error('rate limited after 3 attempts');
}

POST https://api-v2.lithospos.com/v1/token is throttled separately at 30 requests per minute per source address. This is a ceiling for credential-stuffing protection, not a working budget: a healthy integration mints roughly one token per merchant every fifteen minutes.

  • Cache tokens. Reuse a token for its full 900 seconds. See authentication.
  • Page in bulk. List endpoints accept limit up to 100. Pulling 100 rows per call instead of the default 10 cuts a full catalogue sync by an order of magnitude.
  • Read reports, not rows. For totals, /v1/reports/* aggregates server-side. Summing individual sales client-side is slower and far more expensive.
  • Do not poll tightly. Order state changes at human speed. Poll a store’s open orders every 10–15 seconds, not every second.
  • Spread bulk work. Catalogue imports and nightly syncs should run at a steady rate with a small delay between calls rather than in one burst.