Skip to content

Rate limits and feature gates

jtWMS limits how many requests each tenant can make, in two ways: a short-term burst limit and a daily quota. Both count every authenticated request made as your tenant, whether it uses a user token or an API key, and all your users and keys share them.

Each tenant can make up to 100 requests in a burst, refilling at 20 requests per second. A client that sends steadily at 20 requests per second or less never reaches the limit; a client that is idle for 5 seconds can then send 100 requests at once. The burst limit is the same on every plan.

A request over the burst limit gets 429 Too Many Requests:

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 1
{
"title": "Too Many Requests",
"status": 429,
"detail": "Too many requests in a short period. Slow down and retry after the number of seconds in the Retry-After header.",
"errorCode": "burst_limit_exceeded",
"traceId": "00-6f1c0a9d2b6e4c1f8a3b5d7e9f0a1b2c-4d5e6f7a8b9c0d1e-00",
"correlationId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}

Retry-After is the whole number of seconds until a request will be accepted again, at least 1.

Each tenant has a daily request quota set by its plan:

Plan Requests per day
Free 100
Starter 1,000
Pro 10,000
Enterprise Unlimited

Each API Credit Pack add-on adds 5,000 requests per day. The quota resets at midnight UTC.

While a quota applies, every counted response carries two headers:

Header Meaning
X-RateLimit-Limit The tenant’s daily quota.
X-RateLimit-Remaining The requests left today.

Tenants with an unlimited quota get neither header.

A request over the quota gets 429 Too Many Requests with errorCode rate_limit_exceeded:

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1792454400
Retry-After: 30512
{
"title": "Too Many Requests",
"status": 429,
"detail": "You have exceeded your daily API request limit. Upgrade your plan or purchase additional API credits.",
"errorCode": "rate_limit_exceeded",
"traceId": "00-6f1c0a9d2b6e4c1f8a3b5d7e9f0a1b2c-4d5e6f7a8b9c0d1e-00",
"correlationId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}

X-RateLimit-Reset is the next midnight UTC, in Unix seconds, and Retry-After is the seconds until then.

A plan change reaches an API key within about a minute. A user’s access token keeps the quota it was issued with until it is refreshed, at most 15 minutes later.

  • Branch on errorCode: burst_limit_exceeded clears within seconds, while rate_limit_exceeded lasts until midnight UTC.
  • Wait at least the Retry-After seconds before retrying. Don’t retry in a tight loop.
  • Spread bulk work out, and prefer bulk and snapshot endpoints, such as POST /api/v1/products/bulk (up to 500 products per request) and GET /api/v1/products/snapshot, over many single requests.
  • Watch X-RateLimit-Remaining to slow down before the quota runs out.

Some routes belong to a feature module that the tenant’s plan must include. A request to such a route from a tenant whose plan lacks the module gets 403 Forbidden, and isn’t processed:

{
"title": "Forbidden",
"status": 403,
"detail": "Your current plan does not include the 'catalog' module.",
"errorCode": "feature_not_entitled",
"traceId": "00-6f1c0a9d2b6e4c1f8a3b5d7e9f0a1b2c-4d5e6f7a8b9c0d1e-00",
"correlationId": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}

These routes are gated today:

Routes Feature
/api/v1/products/..., /api/v1/product-categories/... catalog
/api/v1/facilities/{facilityId}/inventory/... inventory

Warehouse configuration, webhooks, team and account routes are available on every plan.

A feature gate is different from a missing permission. feature_not_entitled means your plan needs upgrading; a 403 without that code means the user or key lacks a permission (see Permissions and scopes). After an upgrade, an API key gains the feature within about a minute, and a user gains it when their token is next refreshed.