LCX Liberty. American DeFi. Your keys. Your assets. Your control.
Rate limits & quotas
What each plan allows, the headers that tell you where you stand, and what 429 means.
Plans
| Plan | Calls / month | Requests / sec | Apps | Retention |
|---|---|---|---|---|
| Free | 150,000 | 5 | 2 | 30 days |
| Builder | 1,500,000 | 15 | 5 | 30 days |
| Growth | 5,000,000 | 30 | 15 | 90 days |
| Scale | 15,000,000 | 75 | 50 | 180 days |
| Enterprise | Custom | Custom | Custom | Custom |
Every API endpoint is available on every plan. Nothing in the API is feature-gated. The embeddable widget is a separate entitlement, listed on the pricing page. Plans differ only in volume, rate, how many keys you can hold and how much history the dashboard keeps. Pricing has the monthly cost.
Enterprise limits are set by contract rather than by this table, which is why every cell in that column reads Custom. GET /v1/plans returns the figures provisioned for your account, and the headers on every response report the ones actually in force.
A per-minute limit is enforced alongside the per-second one, at exactly 60 times the rate on every plan. Per-second alone punishes the normal bursty shape of a page load. Per-minute alone lets one caller spend a whole minute of budget in a second and starve everyone behind them. The per-second bucket holds two seconds of your rate, so a burst of twice your rps is served before the first 429; sustaining it for a minute is not.
A request is charged by what it cost, not one token each. A call that took longer than about 12 ms of server time is debited extra from the same buckets once it completes, one token per 12 ms and at most 16, so a burst of /v1/quote, /v1/build, /v1/allowance or /v1/permit calls, which do routing work or a round-trip to the chain, empties a bucket in fewer requests than the same burst of /v1/tokens, /v1/price or /v1/prices, which are in-memory reads and cost their one token. This is deliberate: a whale-sized quote costs the engine eight times a retail one, and a limiter that counted requests would measure the wrong thing. The monthly quota is not affected; it counts successful calls, one each.
The plan is the only limit a key meets, and a refusal for it carries Retry-After. The rate belongs to the organisation, as the monthly quota does: every key of an account draws on the same allowance, so a second key separates your workloads' credentials and pins, not their rate. Beneath it sits a flood guard per address, set far above every plan (200 requests a second), which no customer reaches first. The per-endpoint ceilings that used to be described here apply to calls with no key, and those are refused before they are counted.
Headers on every response
| Header | Meaning |
|---|---|
x-liberty-plan | The plan this request was served under. |
x-liberty-ratelimit-limit | Requests per second allowed. |
x-liberty-quota-limit | Calls included this month. |
x-liberty-quota-remaining | Calls left this month. |
Read x-liberty-quota-remaining rather than counting your own calls. It is the number the gateway is actually enforcing. The two quota headers appear on keyed requests only.
What counts
- Failed requests are never counted. A 4xx or 5xx costs you nothing.
- Throttled requests are recorded but not billed. A 429 shows up in your analytics. Without that, a throttled integration looks exactly like an idle one and nothing tells you why traffic dropped.
/v1/chains,/v1/usageand/v1/plansnever count, and they answer even when your quota is exhausted. The endpoint that tells you why you are blocked cannot be the endpoint that is blocked.- MCP calls count as HTTP calls.
Handling 429
Two conditions share the status code and they want opposite responses. RATE_LIMITED means you went over your requests per second, so back off and retry with jitter. QUOTA_EXCEEDED means the month is spent, and retrying will not help until you upgrade or the month rolls over. Branch on the code, not the status.
With a valid key, your plan's rate is the only limit you meet, and going over it is always a plain RATE_LIMITED. An address that keeps calling without a key after it has been refused for going over the per-address limit is blocked for a while instead: TEMPORARILY_BLOCKED, with Retry-After in seconds. Blocks start at 10 minutes and grow for repeat offenders.