API reference
307 capabilities in 23 families, generated from the calculation engine. 307 are callable on /v1 today. Every endpoint is POST https://api.96astro.com/v1/{family}/{capability} with a JSON body (Content-Type: application/json) and answers JSON: data holds the result and meta the request id, credits used and warnings.
Each endpoint below shows its credit cost, headers, every body field (type, required, default, allowed values, limits and an example), an example request in cURL, JavaScript, Python, PHP, Go and both SDKs, a captured example response and the errors it can return. Send the local date and time with an IANA time zone, and places in decimal degrees (see requests and responses).
OpenAPI 3.1 specification
Every endpoint callable today, with its request schema, an example request, an example response, error responses and credit cost (x-credits), in one file for code generators, Postman and API clients. Download the OpenAPI document or fetch it live from https://api.96astro.com/v1/openapi.json (no key needed). Each example response was captured from the live engine with a sandbox key and trimmed for size; AI reading examples are written by hand and marked illustrative. The schema of data is inferred from that example (x-schema-source: example): it shows the shape of one real response, not a contract, so a field may be missing or null in another.
Families
- Birth charts & planets — 12 capabilities. Sidereal birth charts, planet positions, divisional and special-lagna charts, rendered chart images and chart markers.
- Strengths & relationships — 9 capabilities. Ashtakavarga, Shadbala and other strength measures, planetary friendship, avasthas, aspects and dignity tables.
- Dasha systems — 9 capabilities. Planetary and sign-based period systems with their sub-periods, computed from the birth moment.
- Panchang & almanac — 25 capabilities. Daily and monthly panchang, timing tables, calendars, eclipses and planetary events for a date and place.
- Festivals & muhurta — 7 capabilities. Recurring observances, shraddha dates, auspicious-window search and naming syllables.
- Compatibility matching — 13 capabilities. Vedic and South Indian compatibility between two people, from full charts or from birth stars, singly or in bulk.
- Doshas & yogas — 46 capabilities. Dosha checks and classical yoga detection from a birth chart.
- Predictions & readings — 27 capabilities. Rule-based readings: sign horoscopes, transits, characteristics, life readings and period forecasts.
- Krishnamurti Paddhati (KP) — 6 capabilities. KP cusps, significators, ruling planets, horary, transit, ephemeris and birth-time rectification aids.
- Jaimini — 3 capabilities. Chara karakas, Jaimini sign charts and special points.
- Lal Kitab — 7 capabilities. Lal Kitab chart, annual chart, debts, teva, dasha, remedies and predictions.
- Bhrigu Nandi Nadi (BNN) — 8 capabilities. BNN progression charts, nadi relations, graha phala, ratna, yogas and dashas.
- Annual charts (Tajika) — 3 capabilities. Varshaphal and Tithi Pravesh annual charts, sahams and annual dashas.
- Western astrology — 32 capabilities. Tropical natal charts, transits, sun-sign forecasts and synastry.
- Tarot — 15 capabilities. Tarot card draws and fixed spreads.
- Numerology — 5 capabilities. Chaldean/Vedic numerology, name numbers, day numbers and biorhythms.
- Remedies & guidance — 6 capabilities. Gemstone, rudraksha, nakshatra-vastu and Panch Pakshi guidance.
- Reports — 15 capabilities. Long multi-section readings assembled from the chart: topic reports, classical Kundli bundles, matching and longevity.
- Location astrology — 15 capabilities. Astrocartography, relocation, city ranking and place-based timing for a birth chart.
- Vastu — 10 capabilities. Floor-plan Vastu analysis, Ayadi, comparisons, heatmaps and reference tables.
- Mundane astrology — 19 capabilities. World-level forecasting for a moment and place.
- AI interpretation — 8 capabilities. AI-written readings and answers grounded in chart, report or Vastu data the service computes.
- Utilities — 7 capabilities. Languages, place search, time-zone resolution and quick sign finders.
- PDF jobs — 3 operations. Render any report as a branded PDF in the background: create the job, poll it and download the file from its signed link.
https://api.96astro.com/v1{
"data": {},
"meta": {
"request_id": "req_6e985a89a166b73ea220",
"api_version": "v1",
"credits_used": 3,
"warnings": [],
"language": "en"
}
}Authentication
Every request is authenticated with an API key sent in a header. Keys are never accepted in the URL, so they cannot leak into server logs, proxies or browser history.
Authorization: Bearer sk_live_...X-API-Key: sk_live_... is accepted as an alternative for clients that cannot set Authorization.
| Prefix | Environment | Charged | Use it for |
|---|---|---|---|
sk_test_ | Sandbox | No | Development and CI: real calculations, up to 500 calls a day |
sk_live_ | Live | Yes | Production traffic |
A key works only in its own environment. Call the API from your backend: a key inside a mobile app, a single-page app or a theme can be extracted by anyone. Send an Idempotency-Key header with every request so a retry is never charged twice (idempotency).
Your first request
curl -X POST https://api.96astro.com/v1/vedic-charts/planet-positions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209
}'const response = await fetch("https://api.96astro.com/v1/vedic-charts/planet-positions", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209
}),
});
const { data, meta } = await response.json();
console.log(data);import { Astro96Client } from "@96astro/api";
const astro = new Astro96Client({ apiKey: "YOUR_API_KEY" });
const { data, meta } = await astro.vedicCharts.planetPositions({
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209
});
console.log(data);import requests
response = requests.post(
"https://api.96astro.com/v1/vedic-charts/planet-positions",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209,
},
timeout=60,
)
response.raise_for_status()
data = response.json()["data"]
print(data)from astro96_api import Astro96Client
astro = Astro96Client(api_key="YOUR_API_KEY")
res = astro.vedic_charts.planet_positions({
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209,
})
print(res.data)<?php
$ch = curl_init('https://api.96astro.com/v1/vedic-charts/planet-positions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'datetime' => '1990-10-18T14:30:00',
'timezone' => 'Asia/Kolkata',
'latitude' => 28.6139,
'longitude' => 77.209,
]),
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
print_r($result['data']);package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209
}`)
req, err := http.NewRequest("POST", "https://api.96astro.com/v1/vedic-charts/planet-positions", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}Replace YOUR_API_KEY with a sandbox key (sk_test_) to try it free.
Errors
Errors use standard HTTP status codes and one JSON shape. field names the input at fault, or is null when no single field is. Retry only when retryable is true, with exponential backoff and the same idempotency key. You are never charged for an error.
| Status | Codes | Meaning |
|---|---|---|
| 400 | invalid_request | The request could not be read: invalid JSON, a key in the URL, or a bad Idempotency-Key. |
| 401 | invalid_key, expired_key | The API key is missing, invalid, revoked or expired. |
| 402 | payment_required | The plan's payment is overdue past its grace period: live calls stop until it is paid. |
| 403 | account_suspended | The account is not active. |
| 404 | not_found | There is no such capability, job or file. |
| 409 | idempotency_conflict | The Idempotency-Key was reused with a different body, is still in progress, or expired. |
| 410 | link_expired, file_expired | The download link or the file has expired. |
| 413 | payload_too_large | The request body is larger than 1 MiB. |
| 422 | invalid_request, unsupported_language | The input failed validation. |
| 429 | rate_limited, quota_exhausted, spend_cap_reached, project_budget_exceeded | Rate limit reached (retry after Retry-After), credits/quota exhausted, the opt-in overage's monthly spend cap reached (spend_cap_reached: raise the cap or top up; retrying will not help), or the key's project has used its monthly credit budget (project_budget_exceeded: raise the budget or wait for next month; retrying will not help). |
| 500 | computation_failed | The calculation failed on our side. |
| 502 | unavailable | The calculation service returned an unusable answer. |
| 503 | unavailable | The calculation service is temporarily unavailable. |
| 504 | deadline_exceeded | The calculation took too long. |
{
"error": {
"code": "invalid_request",
"message": "Input should be less than or equal to 90",
"field": "latitude",
"request_id": "req_6e985a89a166b73ea220",
"retryable": false
}
}Program against code, which is stable; message is for people and may change.
Rate limits & credits
Each successful call uses credits from your plan; the cost of every endpoint is shown on it and returned in meta.credits_used. Errors are never charged, and sandbox keys never use credits.
| Compute class | Credits per call |
|---|---|
| Light and standard | 1 |
| Heavy | 3 |
| Reports | 10 |
| AI readings | Metered from the same credits: typically 60-170 (fast), 250-750 (balanced) or 1,500-4,000 (deep) |
PDF of a report (POST /v1/jobs/pdf) | The report's 10, plus 120 |
Each plan has a rate limit in units per second, shared by every key of your organization (live and sandbox are counted apart). A call counts units by its compute class:
| Call | Units |
|---|---|
| Light and standard | 1 |
| Heavy | 3 |
| Reports | 10 |
| AI readings | 10, on top of their per-key limit below |
PDF of a report (POST /v1/jobs/pdf) | 10, the report's; the render itself is queued |
Polling a job (GET /v1/jobs/{id}) | 1 |
When credits run out the API answers 429 quota_exhausted, never a silent failure or a surprise bill: top up, upgrade, wait for renewal or turn on capped overage. Sandbox keys allow 500 calls a day per organization.
RateLimit-Limit: 10
RateLimit-Remaining: 7
RateLimit-Reset: 1Over the limit: 429 rate_limited with Retry-After, the seconds until the call would fit.
Languages & labels
language asks for the output language (ISO 639-1). Each endpoint lists the values it supports in its language field; today the AI readings answer in 26 languages and every calculation and report answers in English. Any other value is refused with 422 unsupported_language, whose supported lists what the endpoint takes. Field names, IDs, enum values and numbers never change with language.
labels adds display names without changing the answer: data stays exactly as in English and meta.labels.terms maps each sign, planet, nakshatra and other term in data to its name in that language. Show terms[value] ?? value. Labels are free. Accepted codes:
as bn de es fr gu hi it kn ko ml mr ne nl or pa pl pt ru si ta te tr ur
{
"datetime": "1990-10-18T14:30:00",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.209,
"labels": "hi"
}{
"labels": {
"language": "hi",
"quality": "curated",
"terms": {
"Aries": "मेष",
"Sun": "सूर्य"
}
}
}SDKs & Postman
Official clients for TypeScript/JavaScript (@96astro/api) and Python (astro96-api, import astro96_api) are generated from the OpenAPI document, with retries, idempotency keys, typed errors and PDF job helpers built in (createPdfJob, getJob, downloadFile; snake_case in Python). Methods follow the URL: POST /v1/{family}/{capability} is client.family.capability(), camelCase in TypeScript and snake_case in Python. Both SDKs are built and tested but not on npm or PyPI yet: until they are, contact support for a pre-release package or call the API over HTTP as in the examples.
The Postman collection has every request grouped by family with the documented example body and a saved example response. Import it with an environment (Sandbox or Live), select the environment and paste your key into api_key: the files carry no key. Every request sends Authorization: Bearer {{api_key}} and a fresh Idempotency-Key. Or open the collection directly: Run in Postman.
npm install @96astro/api
pip install astro96-apiPOST /v1/vedic-charts/planet-positions
astro.vedicCharts.planetPositions(input) // @96astro/api
astro.vedic_charts.planet_positions(input) # astro96_api