Skip to content

Rate Limits

Verify endpoints are rate-limited per service by transactions per second (TPS). Every response carries rate-limit headers, and requests over the limit receive 429.

Response headers

Every verify response (success or error) includes:

HeaderDescription
X-RateLimit-LimitYour current per-second request allowance
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetSeconds until the window resets
http
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 49
X-RateLimit-Reset: 1

When you exceed the limit

Over-limit requests return 429 Too Many Requests with a Retry-After header (in seconds):

http
HTTP/1.1 429 Too Many Requests
Retry-After: 1
json
{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded"
  }
}

Handling 429

Back off and retry after the interval in Retry-After. A simple, correct approach:

javascript
async function verifyWithRetry(doRequest, { maxRetries = 3 } = {}) {
  for (let attempt = 0; ; attempt++) {
    const response = await doRequest();
    if (response.status !== 429) return response;
    if (attempt >= maxRetries) throw new Error('Rate limited: retries exhausted');

    const retryAfter = Number(response.headers.get('Retry-After')) || 1;
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
  }
}
typescript
async function verifyWithRetry(doRequest: () => Promise<Response>, maxRetries = 3): Promise<Response> {
  for (let attempt = 0; ; attempt++) {
    const response = await doRequest();
    if (response.status !== 429) return response;
    if (attempt >= maxRetries) throw new Error('Rate limited: retries exhausted');

    const retryAfter = Number(response.headers.get('Retry-After')) || 1;
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
  }
}
python
import time

def verify_with_retry(do_request, max_retries=3):
    for attempt in range(max_retries + 1):
        response = do_request()
        if response.status_code != 429:
            return response
        if attempt >= max_retries:
            raise Exception('Rate limited: retries exhausted')

        retry_after = int(response.headers.get('Retry-After', '1'))
        time.sleep(retry_after)
php
function verifyWithRetry(callable $doRequest, int $maxRetries = 3)
{
    for ($attempt = 0; ; $attempt++) {
        [$status, $headers, $response] = $doRequest();
        if ($status !== 429) {
            return $response;
        }
        if ($attempt >= $maxRetries) {
            throw new Exception('Rate limited: retries exhausted');
        }

        $retryAfter = (int) ($headers['Retry-After'] ?? 1);
        sleep($retryAfter);
    }
}

Reducing rate-limit pressure

  • Watch X-RateLimit-Remaining and slow down before you hit 0.
  • For bulk workloads, use async batch verify — you submit many slips in one request and receive results via webhook, smoothing spikes.
  • Spread traffic evenly rather than bursting; the limit is per-second.

Notes

  • The TPS limit is set per service; contact your account manager if you need a higher limit.
  • Rate-limit headers appear on all verify responses, including 429s.
  • Retry-After is in seconds — honor it rather than retrying immediately.

Bank Slip Verification API for Thai Banking