96Astro API

Documentation

Key restrictions

Scopes, publishable keys for browser widgets, and IP allow-lists. When to use a publishable key and when a secret key.

Every key can be narrowed so that a leaked or misused key can do less. Restrictions are set when you create a key under API keys in the dashboard, and can be changed later; a change applies to the key's next call. A refused call is answered with 403 and is never charged, and nothing is counted against your rate limit or credits.

RestrictionApplies toRefused with
ScopesSecret and publishable keys403 key_scope_denied
Allowed originsPublishable keys403 origin_not_allowed
IP allow-listSecret keys403 ip_not_allowed

Keys created before restrictions existed have none: they can call every capability from anywhere, exactly as before.

Secret or publishable?

Secret key (sk_test_, sk_live_)Publishable key (pk_test_, pk_live_)
Where it livesYour server onlyInside your web page, visible to every visitor
CapabilitiesAll, or the scopes you chooseOnly widget capabilities (below)
Restricted byOptional IP allow-listRequired list of allowed websites (origins)
Rate limitYour plan's units per secondIts own units-per-second allowance, plus 30 calls a minute per visitor IP
PDF and audio jobs, job polling, conversationsYesNo (publishable_key_not_allowed)
X-Credits-Remaining headerLive keysNever: a browser does not see your balance
CORS (callable from a browser)NoYes, from its allowed origins only

Use a secret key for anything server-side: your backend, scripts, mobile app backends, reports, PDFs, audio, photo and AI readings. Never ship it in a browser, app bundle or theme.

Use a publishable key only for a small widget on your own website that calls the API straight from the visitor's browser: today's panchang, a daily horoscope, a basic kundli, a quick match. It is not a secret. Anyone can copy it from your page, so it can do only cheap, read-only widget calls, only from your websites, and only a few times a minute per visitor. Its calls still spend your credits (live) or count toward the sandbox limits (test).

Scopes

A scope list limits a key to some capability families (for example panchang or matching) and, optionally, single capabilities written as family/capability (for example predictions/sign-horoscope-daily). An empty list means every capability.

panchang
matching/quick-match
predictions/sign-horoscope-daily

With these scopes the key can call every panchang capability, the quick match and the daily horoscope, and nothing else. Anything else answers:

{
  "error": {
    "code": "key_scope_denied",
    "message": "This key is not allowed to call /v1/reports/report-marriage. Widen the key's scopes in the dashboard (API keys) or use another key.",
    "field": null,
    "request_id": "req_…",
    "retryable": false
  }
}

Scopes are checked right after the key, before the rate limit, validation or any credit reservation. They also apply to POST /v1/jobs/pdf: the report being rendered must be in scope.

Publishable keys

When you create a publishable key you choose:

  • Allowed origins: the websites that may use it. Each entry is a host, optionally with a scheme and port:

    EntryAllows
    www.example.comhttps://www.example.com only
    *.example.comAny subdomain over https (https://app.example.com, https://a.b.example.com), but not example.com itself: add it separately
    https://shop.example.com:8443That exact scheme, host and port
    http://staging.example.comThat host over plain http
    localhosthttp:// or https://localhost on any port, for development

    Without a scheme only https is allowed (except localhost, 127.0.0.1 and [::1]). The browser's Origin header is checked, or the Referer when there is no Origin; a request with neither (a server or script) is refused with origin_not_allowed. A script can forge these headers, which is why publishable keys are limited to widget capabilities and per-visitor rate limits: use a secret key for anything that matters.

  • Capabilities, from the widget list: daily panchang and its parts (five limbs, sunrise and moonrise, Rahu Kaal and auspicious periods, choghadiya, hora, festivals of the day), daily, weekly and monthly sign horoscopes, kundli basics (planet positions, birth summary, and the chart drawing as SVG: vedic-charts/chart-image-styles), quick, Ashtakoot and Dashakoot matching, place search and the Moon sign, Sun sign and ascendant finders. AI chat can be added too, but only when you switch it on for that key: each reading spends real credits, so set it only for a widget that needs it.

Responses to an allowed origin carry Access-Control-Allow-Origin with that origin, and the browser's CORS preflight is answered for widget capabilities from any origin one of your publishable keys allows. Other origins get no CORS headers, so the browser blocks them.

<div id="panchang"></div>
<script>
  // A publishable key restricted to this website. Not a secret.
  fetch("https://api.96astroapi.com/v1/panchang/daily-panchang", {
    method: "POST",
    headers: {
      "Authorization": "Bearer pk_live_…",
      "Content-Type": "application/json"
    },
    body: JSON.stringify({ date: "2026-10-27", latitude: 28.6139, longitude: 77.209, timezone: "Asia/Kolkata" })
  })
    .then((r) => r.json())
    .then((body) => { document.getElementById("panchang").textContent = JSON.stringify(body.data); });
</script>

Rate limits for publishable keys

  • Their calls count in a separate units-per-second allowance of your plan's size, so a busy widget cannot slow your server-side integration (and creating more publishable keys does not add to it).
  • Each key also allows 30 calls a minute per visitor IP address; past that, the visitor gets 429 rate_limited with Retry-After.

IP allow-lists

A secret key can be limited to your servers' addresses: a list of IPv4 or IPv6 addresses and CIDR ranges, such as 203.0.113.4, 198.51.100.0/24 or 2001:db8::/48 (up to 100 entries). A call from any other address answers 403 ip_not_allowed, which names the address we saw, so you can tell which one to add. An empty list allows every address.

The address is the one that connects to our edge; forwarded headers your client sends are ignored, so they cannot be used to get around the list. If your servers reach the internet through a NAT gateway or proxy, allow-list its public address. The dashboard's playground calls from our web server, so a key with an IP allow-list is refused there; our hosted MCP server passes on the address of your MCP client, which must be in the list.

On this page