Skip to main content

Rate limits

MidasPay protects the platform and downstream acquirers against overload. Concrete per-merchant quotas (requests per second, burst allowances) are set contractually and administered in the Merchant Portal — they are not published here because they vary by merchant tier, channel and region.

Ask your merchant manager

If you need to run a flash sale, back-fill a month of transactions, or otherwise expect sustained high throughput, talk to your MidasPay account manager ahead of time to raise your quota. Hitting a limit at runtime cannot be resolved quickly.

When you've been throttled

A throttled request is rejected with HTTP 429 ResourceExhausted and a MidasPay error code in the response body. The specific code depends on what was throttled:

CodeMeaning
CHANNEL_MARKETING_BUDGET_LIMITEDThe channel's marketing / promotional budget is exhausted. Retry later or disable the promotion.
CHANNEL_MARKETING_TRANSACTIONS_LIMITEDThe channel has hit its transaction-count cap for this merchant or campaign. Retry later.

Additional 429 conditions may be returned when a global platform limit is hit. In all cases, treat 429 as a retryable failure — pause and try again later rather than giving up.

See Error codes for the full catalogue.

Use exponential back-off with full jitter on 429 and on network errors. Cap the retry budget so runaway loops can't pile up:

func call(ctx context.Context, req Request) (*Response, error) {
const (
base = 200 * time.Millisecond
maxSleep = 30 * time.Second
maxAttempts = 6
)
for n := 0; n < maxAttempts; n++ {
resp, err := do(ctx, req)

// 2xx / non-retryable 4xx — stop
if err == nil && resp.StatusCode != 429 && resp.StatusCode < 500 {
return resp, nil
}

// Exponential with full jitter
delay := time.Duration(rand.Int63n(
int64(min(maxSleep, base*(1<<n)))))
select {
case <-time.After(delay):
case <-ctx.Done(): return nil, ctx.Err()
}
}
return nil, ErrTooManyRetries
}
Never retry immediately

Retrying a 429 with no delay just slams the same bucket — leading to cascading failures. Always apply at least a few hundred milliseconds of jittered delay before retrying.

Designing to stay within limits

  • Batch where possible. List endpoints return up to 100 — or 5000 for merchant quotes — records per call. Prefer a small number of large pages over many small ones. See Pagination.
  • Spread bulk jobs over time. Reconciliation that pulls a month of data should scatter calls across many minutes, not tight loops.
  • Cache quotations. MerchantQuote.GetQuotationInfo changes only on contract renegotiation — cache for at least 15 minutes.
  • Idempotency is your friend. A retry-safe client can pause for seconds without losing semantics; see Idempotency.
  • Use webhooks for state. Don't poll order-query in a tight loop — subscribe to the payment-paid event instead. See Webhooks.

FAQ

Where do I see my current quota? In the Merchant Portal → DeveloperAPI quotas. If you can't find it, contact your MidasPay account manager.

Are sandbox and production quotas the same? Sandbox quotas are generally lower to prevent noisy-neighbour testing from affecting the shared environment. Plan production load tests separately with your account manager.

Are webhook deliveries throttled? Inbound webhook delivery (MidasPay → you) is rate-managed separately, and the retry policy is documented in Webhook retry policy.

See also

  • Error codes — full catalogue including 429 responses.
  • Idempotency — so retries are always safe.
  • Pagination — to shape big reconciliation jobs.
  • Webhooks — the preferred alternative to polling.