Rate limits

Complete table of per-IP, per-merchant, and per-partner rate limits.

Overview

JoPay applies rate limits to all API endpoints to prevent abuse and ensure fair usage. When a rate limit is exceeded, the API returns a 429 Too Many Requests response with the error code rate_limited.

Rate limits are enforced at three scopes: per-IP address, per-merchant, and per-partner. Some endpoints have limits at multiple scopes simultaneously.

Rate limit counters use sliding windows. IP addresses are hashed before storage — raw IPs are never persisted. Rate limit buckets are automatically purged after 7 days.

Per-IP limits

These limits apply based on the caller's IP address, regardless of authentication status. They protect public-facing endpoints from abuse.

EndpointLimitWindowNotes
Pay page load601 minuteCustomer-facing payment page. Prevents scraping.
Pay detail / proof2001 hourPayment details and proof submission endpoints.
Events (analytics)1001 hourEvent tracking endpoints.
Fraud reports31 hourAbuse report submission. Intentionally very low to prevent spam.
Proxy (general)1,2001 minuteGeneral proxy route limit. Covers all proxied requests.

Per-merchant limits

These limits apply per authenticated merchant and protect merchant-specific operations.

EndpointLimitWindowNotes
Create payment requestConfigurableVariesSet by the partner. Default varies by partner configuration.
Send invites51 hourMerchant-initiated invite emails.
Recurring operations201 hourCreate, pause, resume, or cancel recurring plans.
Settings updates601 hourMerchant settings changes (display currency, auto-forward, etc.).
Dashboard polling1201 minuteDashboard data refresh. Supports adaptive polling.
Proof submission301 hourSubmitting payment proofs (transaction hashes).

Per-partner limits

These limits apply per partner and protect partner-level administrative operations.

EndpointLimitWindowNotes
Send invites201 hourPartner-initiated merchant invite emails.
FX rate refresh11 minuteManual FX rate refresh trigger. Automatic refreshes are not rate-limited.
Webhook configuration101 minuteWebhook URL updates and test deliveries.

Handling rate limits

When you receive a 429 response, the best approach is:

  1. Do not retry immediately. Wait for the rate limit window to reset.
  2. Use exponential backoff. If you must retry, wait 1 second, then 2, then 4, etc.
  3. Reduce request frequency. If you are hitting poll limits, increase your polling interval.
  4. Check your integration. Hitting rate limits consistently usually indicates a logic issue (e.g., polling in a tight loop).
The JoPay merchant dashboard uses adaptive polling that automatically slows down when the page is not visible or when there is no recent activity. If you are building a custom integration, implement similar backoff logic to stay within limits.

Rate limit response format

When rate-limited, the API returns:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{
  "error": "rate_limited",
  "message": "Too many requests. Please try again later."
}