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
Builder15,000$3960
Launch60,000$99200
Scale300,000$249500

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.