Rate Limits

OpenBoxes Lift enforces rate limits on API requests to ensure fair usage and platform stability. Limits are applied per account (per tenant) and vary by subscription tier. The limit is shared across all of your API keys -- creating additional keys does not increase your quota.

Limits by Tier

Tier Requests per Hour Use Case
Shared 1,000 Small teams, light integrations
Dedicated 25,000 Production integrations, automated workflows
Enterprise Custom (higher limits) High-volume, mission-critical systems

Enterprise limits are set higher than Dedicated and tailored to your integration; contact your account team for details.

Limits apply across all API endpoints combined. There is no per-endpoint breakdown -- a request to /api/v1/products and a request to /api/v1/stockMovements both count toward the same hourly quota. The limit is enforced as a rolling hourly allowance (a token bucket that refills continuously), so you do not need to wait for a fixed reset moment -- capacity returns steadily as the hour passes.

Rate Limit Headers

Every API response includes headers indicating your current rate limit status:

HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1700003600
Content-Type: application/json
Header Type Description
X-RateLimit-Limit integer Your total requests allowed per hour
X-RateLimit-Remaining integer Requests remaining in the current window
X-RateLimit-Reset integer Unix timestamp when the window resets

Checking Your Limits

Read the rate limit headers from any API response:

curl -s -D - -H "X-API-Key: $OB_API_KEY" \
  "https://acme.openboxes.cloud/api/v1/products?max=1" \
  -o /dev/null 2>&1 | grep -i "x-ratelimit"

Example output:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 612
X-RateLimit-Reset: 1700003600

Handling 429 Responses

When you exceed the rate limit, the API returns HTTP 429 Too Many Requests with this JSON body:

{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded. Limit: 1000 requests per hour. Reset at: 1700003600",
  "limit": 1000,
  "reset_at": 1700003600
}

limit is your hourly ceiling and reset_at is the Unix timestamp when capacity next becomes available (i.e. when your next request will be allowed). Because the allowance refills continuously, that is typically only a few seconds away, not a full hour. The response also includes a Retry-After header indicating how many seconds to wait before retrying:

HTTP/1.1 429 Too Many Requests
Retry-After: 3
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700003600

Implementing Retry Logic

Always implement exponential backoff when encountering rate limits:

#!/bin/bash
# Simple retry with backoff

MAX_RETRIES=3
RETRY_COUNT=0

make_request() {
  response=$(curl -s -w "\n%{http_code}" -H "X-API-Key: $OB_API_KEY" \
    "https://acme.openboxes.cloud/api/v1/products?max=25&offset=$1")

  http_code=$(echo "$response" | tail -1)
  body=$(echo "$response" | head -n -1)

  if [ "$http_code" = "429" ]; then
    RETRY_COUNT=$((RETRY_COUNT + 1))
    if [ $RETRY_COUNT -le $MAX_RETRIES ]; then
      wait_time=$((2 ** RETRY_COUNT * 10))
      echo "Rate limited. Waiting ${wait_time}s before retry $RETRY_COUNT..."
      sleep $wait_time
      make_request "$1"
    else
      echo "Max retries exceeded."
      exit 1
    fi
  else
    echo "$body"
  fi
}

make_request 0

Best Practices

Minimize Unnecessary Requests

Cache responses that do not change frequently:

# Bad: fetching all locations on every sync cycle
# (locations rarely change, burns through your quota)
while true; do
  curl -H "X-API-Key: $OB_API_KEY" ".../api/v1/locations"
  sleep 60
done

# Good: cache locations, refresh once per hour
curl -H "X-API-Key: $OB_API_KEY" ".../api/v1/locations" > /tmp/locations_cache.json
# Use cached data for the next hour

Use Pagination Efficiently

Fetch data in reasonable batch sizes instead of making many small requests:

# Bad: fetching one product at a time (100 requests for 100 products)
for id in $product_ids; do
  curl -H "X-API-Key: $OB_API_KEY" ".../api/v1/products/$id"
done

# Good: fetch in batches (4 requests for 100 products)
for offset in 0 25 50 75; do
  curl -H "X-API-Key: $OB_API_KEY" ".../api/v1/products?max=25&offset=$offset"
done

Monitor Your Usage

Track the X-RateLimit-Remaining header to detect when you are approaching your limit:

remaining=$(curl -s -D - -H "X-API-Key: $OB_API_KEY" \
  "https://acme.openboxes.cloud/api/v1/products?max=1" \
  -o /dev/null 2>&1 | grep -i "x-ratelimit-remaining" | tr -d '\r' | cut -d' ' -f2)

if [ "$remaining" -lt 100 ]; then
  echo "WARNING: Only $remaining API requests remaining this hour"
fi

Spread Requests Over Time

Avoid bursting all requests at the start of each hour. Distribute your API calls evenly:

# Bad: sync everything at the top of the hour
0 * * * * /scripts/full_sync.sh  # 500 requests in 2 minutes

# Good: stagger sync tasks across the hour
0 * * * * /scripts/sync_products.sh     # ~50 requests
15 * * * * /scripts/sync_inventory.sh   # ~100 requests
30 * * * * /scripts/sync_orders.sh      # ~75 requests
45 * * * * /scripts/sync_movements.sh   # ~80 requests

Cache and Batch

Every API call counts against your limit. Cache data that changes infrequently, batch with pagination, and avoid polling tighter than you need. See Authentication for how requests are authenticated.

Upgrading Your Limit

If your integration needs exceed your current tier's limits:

Current Tier Upgrade Path
Shared (1,000/hr) Upgrade to Dedicated for 25x the capacity
Dedicated (25,000/hr) Contact sales for Enterprise with custom limits
Enterprise Adjust limits through your account team

Visit the Pricing page or contact your account manager to discuss tier upgrades.

Frequently Asked Questions

Do rate limits apply to the OpenBoxes web UI? No. Rate limits only apply to API requests (calls to /api/v1/*). Normal browser usage of the OpenBoxes application is not rate-limited.

Which requests are counted? Every API request (any call to /api/v1/*) counts toward your hourly limit. There is no separate login call to authenticate -- you send the X-API-Key header on each request -- so cache and batch to stay under your limit.

What happens if I consistently hit the limit? Persistent rate limit violations may indicate that you need a higher tier. Lift does not suspend accounts for hitting rate limits, but sustained 429 responses will degrade your integration's performance.

Can I request a temporary limit increase? Enterprise tier customers can request temporary limit increases for data migration or one-time bulk operations through their account team.