Skip to main content
ReconLayer applies a request-rate limit to protect the API and your organization’s workloads from runaway clients.

Default limit

300 requests per minute, per organization.
The limit is keyed by your resolved organizationId — every credential (API key or Clerk session) belonging to the same organization shares the same 300-requests-per-minute budget. Requests that don’t resolve to an organization (which should not normally happen for authenticated /v1/* routes) are keyed by IP address instead. Both the request ceiling and the time window are configurable per deployment via environment variables:
Env varDefaultMeaning
RATE_LIMIT_MAX300Maximum requests allowed per window, per organization.
RATE_LIMIT_WINDOW1 minuteThe rolling time window the limit applies over.
If you’re operating a high-volume integration and need a higher limit, contact ReconLayer support — limits are configured at the deployment level.

Public paths are not rate-limited

/health, /openapi.json, /openapi.yaml, /docs (and /docs/*), and /webhooks/* are exempt from rate limiting — the same allow-list used for public, unauthenticated routes.

Response headers

Every response from a rate-limited route carries headers describing your current budget:
HeaderMeaning
x-ratelimit-limitThe configured maximum requests per window (RATE_LIMIT_MAX).
x-ratelimit-remainingRequests remaining in the current window.
x-ratelimit-resetSeconds until the current window resets.
HTTP/1.1 200 OK
x-ratelimit-limit: 300
x-ratelimit-remaining: 287
x-ratelimit-reset: 42

Exceeding the limit — 429

Once your organization exceeds RATE_LIMIT_MAX requests within RATE_LIMIT_WINDOW, ReconLayer responds with 429 Too Many Requests and adds a retry-after header (in seconds) indicating when the window resets:
HTTP/1.1 429 Too Many Requests
x-ratelimit-limit: 300
x-ratelimit-remaining: 0
x-ratelimit-reset: 38
retry-after: 38
429 Too Many Requests
{
  "statusCode": 429,
  "error": "Too Many Requests",
  "message": "Rate limit exceeded, retry in 1 minute"
}

Handling 429s

1

Read retry-after

Use the retry-after header (seconds) to decide how long to wait before your next request — don’t guess or use a fixed backoff that ignores it.
2

Back off and retry

For idempotent writes, retry with the same Idempotency-Key and request body after the indicated delay — see Idempotency.
3

Spread bursty workloads

If you’re paginating through a large list (e.g. an export or bulk reconciliation sweep), add a small delay between pages rather than firing requests as fast as possible. See Pagination.
4

Watch x-ratelimit-remaining proactively

Slow down before you hit 0 rather than reacting only to 429s — this avoids latency spikes from forced retries.

Example: backoff loop

until response=$(curl -s -w "%{http_code}" -o /tmp/body \
    "http://localhost:3001/v1/payment-intents?limit=25&offset=0" \
    -H "Authorization: Bearer $RECONLAYER_API_KEY" \
    -D /tmp/headers); do
  sleep 1
done

if [ "$response" = "429" ]; then
  retry_after=$(grep -i '^retry-after:' /tmp/headers | awk '{print $2}' | tr -d '\r')
  echo "Rate limited, retrying in ${retry_after}s"
  sleep "$retry_after"
fi

Next steps

  • Errors — the full error catalog, including other 4xx/5xx statuses.
  • Idempotency — safely retrying write requests after a 429 or 5xx.
  • Authentication — how the organization that rate limits are keyed on is resolved.