Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.smartretry.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

SmartRetry applies rate limits to ensure fair usage and protect the platform from abuse. This page explains the limits and how to handle them gracefully.

Rate limits

Endpoint typeLimitWindow
Payment operations (sale, capture, refund, void)100 requestsper second
Status queries500 requestsper second
Recurring operations100 requestsper second
All endpoints combined1,000 requestsper second
Limits are applied per API key. Contact support@smartretry.com if you need higher limits.

Rate limit headers

Every response includes headers showing your current usage:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1711979533
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Handling rate limits

When you exceed the rate limit, SmartRetry returns a 429 Too Many Requests response:
{
  "type": "https://api.smartretry.com/errors/rate-limit",
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Rate limit exceeded. Retry after 1 second.",
  "reason_code": "RATE_LIMIT_EXCEEDED"
}
The response includes a Retry-After header indicating how long to wait:
Retry-After: 1

Exponential backoff

Implement exponential backoff to handle rate limits and transient errors gracefully. This strategy progressively increases wait times between retries to avoid overwhelming the API.
import requests
import time
import random

def make_request_with_backoff(url, headers, json_data, max_retries=5):
    """Make an API request with exponential backoff retry logic."""
    base_delay = 1  # Start with 1 second
    max_delay = 60  # Cap at 60 seconds

    for attempt in range(max_retries):
        response = requests.post(url, headers=headers, json=json_data)

        if response.status_code == 200:
            return response.json()

        if response.status_code == 429:
            # Use Retry-After header if available
            retry_after = response.headers.get("Retry-After")
            if retry_after:
                delay = int(retry_after)
            else:
                # Exponential backoff with jitter
                delay = min(base_delay * (2 ** attempt), max_delay)
                delay += random.uniform(0, delay * 0.1)  # Add 10% jitter

            print(f"Rate limited. Retrying in {delay:.1f} seconds...")
            time.sleep(delay)
            continue

        if response.status_code >= 500:
            # Server error - retry with backoff
            delay = min(base_delay * (2 ** attempt), max_delay)
            delay += random.uniform(0, delay * 0.1)
            print(f"Server error. Retrying in {delay:.1f} seconds...")
            time.sleep(delay)
            continue

        # Client error (4xx except 429) - don't retry
        response.raise_for_status()

    raise Exception(f"Max retries ({max_retries}) exceeded")


# Example usage
response = make_request_with_backoff(
    "https://api.smartretry.com/v1/payments/sale/ABC123",
    headers={
        "x-api-key": "YOUR_API_KEY",
        "Content-Type": "application/json",
        "Idempotency-Key": "order-123"
    },
    json_data={
        "amount": 49.99,
        "currency": "USD",
        # ... other fields
    }
)

Best practices

Use idempotency keys

Always include an Idempotency-Key header on POST requests. This ensures retried requests don’t create duplicate transactions.

Add jitter

Add random jitter to retry delays to prevent thundering herd problems when multiple clients retry simultaneously.

Monitor remaining quota

Check X-RateLimit-Remaining headers and throttle proactively before hitting limits.

Batch when possible

For high-volume operations, use bulk endpoints (coming soon) instead of individual requests.

Retry decision matrix

Status codeRetry?Strategy
200NoSuccess
400NoFix request and resubmit
401NoCheck API key
404NoCheck resource ID
409MaybeCheck idempotency; may be success
429YesUse Retry-After header
500YesExponential backoff
502YesExponential backoff
503YesUse Retry-After if present
504YesExponential backoff
Never retry 400 Bad Request errors automatically. These indicate a problem with your request that must be fixed before resubmitting.
For payment operations, a 409 Conflict with an idempotency key often means the original request succeeded. Check the response body for the transaction ID before retrying.