Rate Limiting

The Batchmates API implements rate limiting to ensure service stability. Rate limits are applied per IP address for unauthenticated requests and per user for authenticated requests.


Rate Limit Tiers

Different endpoint types have different rate limits:

  • Name
    Login Endpoints
    Type
    10 requests/minute
    Description

    /v1/mobile/auth/login, /v1/web/auth/login

    Strictly limited to prevent brute-force attacks.

  • Name
    Payment / Charge Endpoints
    Type
    5 requests/minute
    Description

    POST /payments/magpie/create-source, POST /payments/magpie/create-wallet-source, POST /donations/charge-saved, POST /donations/{id}/pay/magpie

    Tightly limited to prevent payment abuse and card enumeration.

  • Name
    General API
    Type
    120 requests/minute
    Description

    All other authenticated endpoints

    Standard limit for normal API usage. Window resets every 60 seconds.

###Per-User vs Per-IP

  • Authenticated requests: Limits apply per user account
  • Unauthenticated requests: Limits apply per IP address

Response Headers

Every API response includes rate limit information:

HTTP/1.1 200 OK
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 115
X-RateLimit-Reset: 1707217200
  • Name
    X-RateLimit-Limit
    Type
    integer
    Description

    Maximum requests allowed in the current window

  • Name
    X-RateLimit-Remaining
    Type
    integer
    Description

    Number of requests remaining in current window

  • Name
    X-RateLimit-Reset
    Type
    integer
    Description

    Unix timestamp (seconds) when the rate limit resets

Example Response

curl -I https://batchmates-v2.revlv.com/api/v1/campaigns \
  -H "Authorization: Bearer {token}"
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1707217200

Rate Limit Exceeded

When you exceed the rate limit, the API returns HTTP 429:

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

{
  "success": false,
  "message": "Too many requests. Please try again later."
}

Retry-After Header

The Retry-After header indicates how many seconds to wait before retrying:

  • Name
    Retry-After
    Type
    integer
    Description

    Number of seconds until rate limit resets


Example: Monitoring Rate Limits

const response = await fetch('https://batchmates-v2.revlv.com/api/v1/campaigns', {
  headers: { 'Authorization': `Bearer ${token}` }
});

const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const reset = parseInt(response.headers.get('X-RateLimit-Reset'));

console.log(`${remaining}/${limit} requests remaining`);
console.log(`Resets at: ${new Date(reset * 1000).toLocaleString()}`);

Common Scenarios

Scenario 1: Login Rate Limit

# Attempt 11th login in one minute
curl -X POST https://batchmates-v2.revlv.com/api/v1/mobile/auth/login \
  -d "email=user@example.com" \
  -d "password=wrong"
{
  "success": false,
  "message": "Too many requests. Please try again later."
}

Solution: Wait 60 seconds for the rate limit to reset.

Scenario 2: General API Limit

# Make 121st request in one minute
curl https://batchmates-v2.revlv.com/api/v1/campaigns \
  -H "Authorization: Bearer {token}"
HTTP/1.1 429 Too Many Requests
Retry-After: 30

Solution: Wait 30 seconds (or check Retry-After header) before retrying.


Rate Limit by Endpoint Type

Endpoint TypeLimitWindowScope
Login10/min60sPer IP
Payment / Charge5/min60sPer User
General API120/min60sPer User
WebhooksUnlimited-N/A

Troubleshooting

Issue: Hitting Login Rate Limit

429 Too Many Requests on /v1/mobile/auth/login

Cause: More than 10 login attempts in 60 seconds

Solution:

  • Wait for rate limit to reset
  • Use refresh tokens instead of logging in repeatedly
  • Store and reuse JWT tokens

Issue: Hitting General API Limit

429 Too Many Requests on /v1/campaigns

Cause: More than 120 API requests in 60 seconds

Solution:

  • Reduce request frequency
  • Use pagination efficiently
  • Cache responses where appropriate
  • Use webhooks instead of polling for status updates

Was this page helpful?