Rate Limits
OpenBoxes Lift enforces rate limits on API requests to ensure fair usage and platform stability. The hourly limits on this page apply to API-key traffic: requests carrying your X-API-Key. They are applied per account (per tenant) and depend on your subscription tier and any API add-on on your plan. The limit is shared across all of your API keys; creating additional keys does not increase your quota.
The Reporting API is the exception: it has its own separate allowance (see The Reporting API's own allowance below), so reporting requests never use up the limits on this page.
The customer portal is not charged against this allowance. It has its own separate per-person limit, set far above anything ordinary portal use reaches, so signing in to the portal and using it never consumes your API quota.
Limits by Tier#
| Tier | Requests per Hour (included) | With an API add-on | Use Case |
|---|---|---|---|
| Shared | 1,000 | 2,000 (API 2×, $30/mo or $288/yr) or 5,000 (API 5×, $70/mo or $672/yr) | Small teams, light integrations |
| Dedicated | 25,000 | 50,000 (API 2×, $175/mo or $1,680/yr) | Production integrations, automated workflows |
| Enterprise | 50,000 | 100,000 (API 2×, +$300/mo) or 200,000 (API 4×, +$525/mo), as contract line items | High-volume, mission-critical systems |
On Shared and Dedicated you raise the limit yourself: go to Billing in the portal, open the Add-ons card, click Browse add-ons and add an API band. One API band can be active at a time (on Shared, to move between 2× and 5×, remove the current band and add the other), and add-ons are available once your subscription is paid, not during the trial. Enterprise agreements include 50,000 requests per hour; the 2× and 4× bands are added to the agreement through sales@openboxes.cloud. See Billing & Plans for how add-ons are charged and cancelled.
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.
An API add-on raises this hourly allowance. Once it is active, X-RateLimit-Limit reports the new ceiling. It does not change the platform's short-burst protection, which applies to every account alike regardless of plan or add-on, so a larger hourly allowance is still best used by spreading requests over time (see Best Practices below) rather than sending them all at once.
The Reporting API's own allowance#
The Reporting API (https://api.openboxes.cloud/api/v1/reporting) has its own allowance of 600 requests an hour per account, on every plan. It is not counted against the limits above, and requests to the rest of the API are not counted against it. An API add-on raises the limits above, not the reporting allowance. It holds 600 requests that you can use at once, then gives one more back every 6 seconds, and its responses carry X-RateLimit-Bucket: reporting so you can tell the two apart. The Reporting API page explains what counts, what does not, and a worked example for a Power BI refresh.
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 | On a successful response, one hour from now. Your allowance refills continuously, so this is not when capacity comes back; on a 429, reset_at and Retry-After say when the next request is allowed |
X-RateLimit-Bucket |
string | Only on Reporting API responses: reporting, meaning the figures above are the reporting allowance |
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
}
A Reporting API request that runs out of the reporting allowance gets the same status with "bucket": "reporting" in the body:
{
"error": "rate_limit_exceeded",
"bucket": "reporting",
"message": "Reporting API limit reached: 600 requests per hour. Your other API calls are not affected. Try again after the reset time.",
"limit": 600,
"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 limit:
| Current Tier | Options |
|---|---|
| Shared (1,000/hr) | Add API 2× (2,000/hr, $30/mo) or API 5× (5,000/hr, $70/mo) under Billing > Add-ons, or move to Dedicated (25,000/hr) |
| Dedicated (25,000/hr) | Add API 2× (50,000/hr, $175/mo) under Billing > Add-ons, or contact sales for Enterprise (50,000/hr included) |
| Enterprise (50,000/hr) | API 2× (100,000/hr, +$300/mo) or 4× (200,000/hr, +$525/mo) as contract line items; contact sales |
Add-ons take effect once the row on your Billing page shows Active (usually within a minute of the purchase; the new ceiling can take a few minutes to reach every request) and are charged pro-rata for the rest of the current period, then with your plan. While an API add-on is active, moving between Shared and Dedicated hosting is arranged with support rather than as a self-serve plan change. Visit the Pricing page for the full list, or contact sales@openboxes.cloud about Enterprise.
Frequently Asked Questions#
Do rate limits apply to the OpenBoxes web UI?
No. The hourly limits on this page apply to API-key requests. Normal browser usage of the OpenBoxes application is not rate-limited. This works the same way on Shared and Dedicated: the limit counts requests to /api/v1 that carry your API key, apart from Reporting API requests, which have their own allowance (see below). Nothing else is counted.
Does using the customer portal use up my API quota? No. The portal has its own separate per-person limit, set far above anything ordinary portal use reaches, and portal traffic is never charged against the hourly API limits above. It is a safety ceiling on our own interface, not a plan allowance, so it is not comparable with the hourly API numbers in the table. A higher-tier plan does not come with a bigger portal limit, and you should never need to think about it. Each signed-in person has their own, so one busy colleague cannot use up another's.
Which requests are counted?
Every API-key request (any X-API-Key call to /api/v1/*) counts toward your hourly limit, except Reporting API requests, which count toward the reporting allowance instead. 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.
Does the Reporting API count? No, not against the limits on this page. The Reporting API has its own 600 requests an hour per account on every plan, and the API add-on does not change it. See Reporting API.
What happens if I consistently hit the limit?
Persistent rate limit violations usually mean you need an API add-on or 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 customers can request a temporary limit increase for a data migration or one-time bulk operation through support.