Rate limits
API requests are rate-limited based on your subscription tier and applied per API key.
Usage is tracked against two meters:
- Chart requests: Every call to a Chart API endpoint (chart, composite, astrology, transits, returns, retrogrades, multi-chart). Most calls count as 1 chart request; transit ranges and multi-chart batches count more.
- SAGE responses: Every answered SAGE query. One query is one SAGE response (0 on a cache hit).
These meters are independent. A chart request does not draw down SAGE responses.
Tier limits
Every key includes the Free floor. Paid tiers add allowances on top of this floor.
| Tier | Chart requests / mo | SAGE responses / mo | Rate limit | MCP scope | Cap behavior |
|---|---|---|---|---|---|
| Free | 100 | 25 | 10 RPM | None | Hard cap |
| Chart | 20,000 | — | 60 RPM | None | Hard cap |
| SAGE | — | 3,000 | 100 RPM | SAGE tools | Hard cap |
| Advanced | 40,000 | 4,000 | 120 RPM | Chart + SAGE tools | Soft cap |
| Pro | 100,000 | 10,000 | 300 RPM | Chart + SAGE tools | Soft cap |
| Enterprise | Unlimited | Unlimited | Custom | Custom | Soft cap |
Chart is $22/mo or $199/yr. SAGE is $29/mo or $299/yr. Advanced is $44/mo or $399/yr. Pro is $100/mo or $899/yr. Enterprise is by contact. SAGE queries run at roughly 100 RPM regardless of tier.
Free is not a separate signup. Every key includes at least 100 chart requests and 25 SAGE responses per month. A paid tier adds its allowance on top of this floor.
Active subscriptions sum their allowances. You can hold up to 3 active subscriptions per product. A second Chart subscription provides 40,000 chart requests.
Metered actions
Most endpoints count 1 chart request per call. Transit ranges and SAGE queries scale based on the request:
| Endpoint type | Meter | Count |
|---|---|---|
Chart endpoints (/api/chart, /api/composite, /api/astrology) | Chart requests | 1 per call |
Multi-chart batch (/api/multi-chart) | Chart requests | 1 per successful chart |
Planetary returns (/api/returns) | Chart requests | 1 per request |
| Transit endpoints (daily granularity) | Chart requests | 1 per day in range |
| Transit endpoints (hourly granularity) | Chart requests | 3 per day in range |
| Transit endpoints (minute granularity) | Chart requests | 10 per day in range |
Transit periods (/api/transits/periods) | Chart requests | 1 per request |
Retrograde periods (/api/retrogrades) | Chart requests | 1 per request |
SAGE query (/api/sage) | SAGE responses | 1 per answer (0 on cache hit) |
MCP tool calls (/mcp) | Same as the wrapped REST endpoint | — |
Failed requests (4xx/5xx responses) do not count against either meter.
Rate limit and quota headers
API responses include these rate limit and quota headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per minute for this key |
X-RateLimit-Remaining | Requests remaining in the current 60-second window |
X-Quota-Meter | Which meter this response counted against: chart or sage |
X-Quota-Limit | Monthly allowance for that meter |
X-Quota-Used | Amount of that meter consumed this billing period |
X-Quota-Remaining | Amount of that meter remaining this billing period |
The X-Quota-* headers describe the meter named in X-Quota-Meter. Chart endpoints report chart; SAGE queries report sage. Use these headers to track remaining allowances.
Exceeding limits
When you exceed the per-minute rate limit, the API returns a 429 Too Many Requests response:
{
"success": false,
"error": "Rate limit exceeded",
"message": "Your plan allows 120 requests per minute. Please slow down.",
"retryAfter": 60
}
When your monthly allowance for a meter is exhausted, the API returns a 429 naming the exhausted meter:
{
"success": false,
"error": "Monthly Chart request limit reached",
"meter": "chart",
"limit": 20000,
"used": 20000,
"upgrade_url": "https://studio.totalhumandesign.com/dashboard/billing"
}
SAGE returns the same response shape with "meter": "sage". Subscribe to a higher tier or wait for the next billing period to reset.