Skip to content

Rate Limits

Every Genius Checkout API endpoint sits in one of three tiers. Limits are per-API-key (per-merchant for authenticated traffic, per-IP for unauthenticated traffic) and refresh on a rolling one-minute window.

Tiers

TierLimitWhat it covers
payment-mutations60 / minuteMoney-moving writes — create payment, refund, capture, void, tokenize, charge-token, create subscription, cancel subscription, deactivate token
writes120 / minuteReads + non-money writes — list/get any resource, create/pause/archive payment link, pause/resume subscription, Zapier subscribe/unsubscribe
public-reads300 / minuteUnauthenticated read paths (currently used only by public payment-link rendering)

Endpoint → tier reference

EndpointTier
POST /payments, POST /payments/{id}/capture, POST /payments/{id}/refund, POST /payments/{id}/voidpayment-mutations
GET /payments/{id}writes
POST /checkout-sessionswrites
GET /checkout-sessions/{id}writes
POST /tokenize, POST /charge-tokenpayment-mutations
POST /subscriptions, POST /subscriptions/{id}/cancelpayment-mutations
GET /subscriptions, GET /subscriptions/{id}, POST /subscriptions/{id}/pause, POST /subscriptions/{id}/resume, PUT /subscriptions/{id}/payment-methodwrites
GET /transactions, GET /customers, GET /customers/{id}/payment-tokenswrites
POST /payment-tokens/{id}/deactivatepayment-mutations
GET /payment-links, POST /payment-links, GET /payment-links/{id}, POST /payment-links/{id}/*writes
POST /zapier/subscriptions, DELETE /zapier/subscriptions/{id}, GET /zapier/sample-paymentswrites

Response headers

Every authenticated response carries:

HeaderMeaning
X-RateLimit-LimitMaximum requests in the current window for this tier
X-RateLimit-RemainingRequests left before the next 429

When you breach the limit, the 429 response additionally includes:

HeaderMeaning
Retry-AfterSeconds until the window resets

429 body

json
{
  "error": "Too many requests. Please try again later.",
  "retry_after": 17
}

retry_after matches the Retry-After header in seconds.

Backoff guidance

  • Always honor Retry-After — don't poll harder.
  • Use exponential backoff with jitter if you can't read the header (e.g., a third-party HTTP client that swallows it): min(60s, base * 2^n + random(0, 1s)) starting at base = 1s.
  • For batch jobs (mass refunds, bulk re-charges), stay below 50/min on payment-mutations to leave headroom for any in-flight customer-driven traffic on the same key.
  • Use Idempotency-Key on every retry so you can safely re-fire a request without double-charging.
js
async function callWithBackoff(url, init, attempt = 0) {
  const res = await fetch(url, init)
  if (res.status !== 429) return res
  const wait = Number(res.headers.get('Retry-After')) || 2 ** attempt
  await new Promise(r => setTimeout(r, wait * 1000))
  return callWithBackoff(url, init, attempt + 1)
}
python
# Python — same pattern with `requests`
import requests, time
def call_with_backoff(method, url, **kwargs):
    for attempt in range(6):
        r = requests.request(method, url, **kwargs)
        if r.status_code != 429:
            return r
        wait = int(r.headers.get('Retry-After', 2 ** attempt))
        time.sleep(wait)
    return r

Burst headroom

Limits are evaluated per-key. Splitting traffic across multiple API keys is not a sanctioned way to multiply your effective limit — if you need higher throughput on a single merchant account, contact support and we can raise the tier on your key.

Next

Released under the proprietary Genius Checkout license.