Skip to main content

Rate Limits

Asterwise applies three independent rate limits per request:

  1. IP burst limit — protects against unauthenticated abuse from a single IP
  2. Tier monthly quota — the call budget for your plan, resets monthly
  3. Tier burst limit — caps the rate of authenticated requests within a single minute

All three limits emit the canonical error envelope with a specific error code and an HTTP Retry-After header. Standard HTTP retry middleware (urllib3 Retry, axios-retry, fetch-retry, Cloudflare, AWS WAF) will automatically honor the header without custom code.

Plan quotas​

PlanMonthly callsPriceTier burst limit (per minute)
Sandbox500Free10
Builder10,000$1060
Launch50,000$30200
Scale300,000$100500
EnterpriseCustomCustomCustom

Calls that fail with a 4xx status code are not counted against your monthly quota. Calls that return 5xx are not counted either — only successful 2xx responses consume quota.

IP burst limit (unauthenticated)​

Every IP is limited to 60 requests per minute across all endpoints. This applies before authentication, so requests without an API key still count.

When triggered, the response is:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-Request-Id: <uuid>

{
"success": false,
"error": "ip_rate_limit_exceeded",
"message": "Too many requests from this IP address. Try again in 60 seconds.",
"details": [],
"retry_after": 60,
"doc_url": "https://docs.asterwise.com/reference/errors/ip_rate_limit_exceeded",
"request_id": "<uuid>",
"timestamp": "<ISO 8601 UTC>"
}

Tier monthly quota​

When you exceed your monthly quota, the response is:

HTTP/1.1 429 Too Many Requests
X-Request-Id: <uuid>

{
"success": false,
"error": "monthly_usage_limit_exceeded",
"message": "You have reached your monthly call limit. Upgrade at asterwise.com/dashboard to get more calls.",
"details": [],
"retry_after": null,
"doc_url": "https://docs.asterwise.com/reference/errors/monthly_usage_limit_exceeded",
"request_id": "<uuid>",
"timestamp": "<ISO 8601 UTC>"
}

retry_after is null for monthly limits because the wait time depends on the calendar — your quota resets on the 1st of each month UTC.

Tier burst limit (authenticated)​

Authenticated requests are also rate-limited per minute by tier:

TierBurst limit (per minute)
Sandbox10
Builder60
Launch200
Scale500

When exceeded:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-Request-Id: <uuid>

{
"success": false,
"error": "burst_limit_exceeded",
"message": "Too many requests in the last minute. Try again shortly.",
"details": [],
"retry_after": 60,
"doc_url": "https://docs.asterwise.com/reference/errors/burst_limit_exceeded",
"request_id": "<uuid>",
"timestamp": "<ISO 8601 UTC>"
}

Response headers​

Every rate-limit response carries:

HeaderValueWhen set
Retry-AfterInteger secondsOn every retry-bearing rate-limit response. Conforms to RFC 7231 §7.1.3.
X-Request-IdUUIDAlways. Use for support tracing.
X-RateLimit-LimitIntegerYour monthly call budget.
X-RateLimit-PlanStringYour plan name (sandbox, builder, launch, scale).

Subscription expiry​

Distinct from rate limits but on the same code path: if your subscription expires, requests return subscription_expired with a 402 status code. The message includes the upgrade URL. No Retry-After — renew your subscription at the dashboard.

Best practices​

Honor Retry-After​

Most HTTP clients respect Retry-After automatically:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
respect_retry_after_header=True, # default in urllib3 1.26+
)
session.mount("https://", HTTPAdapter(max_retries=retry_strategy))

response = session.get(
"https://api.asterwise.com/v1/astro/ayanamsha",
headers={"Authorization": "Bearer YOUR_KEY"},
)

Distribute calls across the minute​

For high-throughput applications, smooth your request rate. If you have a daily batch of 1,000 charts to compute on the Builder plan (60/min burst limit), distribute them across the day rather than firing them all at once.

Use idempotency for retry safety​

GET requests are idempotent by definition. POST endpoints are also idempotent on Asterwise — sending the same payload twice produces the same chart, no duplicate side effects. Safe to retry POSTs without idempotency keys.

Monitor X-RateLimit-Limit proactively​

Track your monthly consumption against X-RateLimit-Limit so you can upgrade before you hit the quota wall. The dashboard at asterwise.com/dashboard shows real-time usage.

What happens during a Redis outage​

Asterwise uses Redis to track rate-limit counters. If Redis is temporarily unreachable, rate limiting fails open — your requests succeed even if you would have been rate-limited. This is intentional: availability outweighs perfect quota enforcement during an infrastructure incident. Monthly quota tracking resumes when Redis recovers.

You will not be charged for requests served during a Redis outage unless they would have counted normally.