96Astro API

Documentation

Platforms and frameworks

How to call the 96Astro API from your stack - web frameworks, mobile apps, server languages, serverless functions, website builders and automation tools.

The API is plain HTTPS and JSON, so it works from any platform that can send a POST request. There are three ways in:

Way inUse it forKey
Any HTTP client (or our SDKs for TypeScript, Python and PHP)Every capability, from your server or a serverless functionSecret key sk_test_ / sk_live_, kept on the server
Widgets (one script tag)Ready-made panchang, horoscope, kundli, matching and AI chat panels on a web pagePublishable key pk_, limited to your domains
WordPress pluginWordPress sitesSecret key, stored in WordPress

Every example below makes the same call as the Quickstart: planet positions for a birth moment. Swap the path and body for any other capability; the API reference lists them, and the API explorer writes the request for you in about 20 languages.

Never put a secret key in a browser, a mobile app or a theme. Anyone can read it there and spend your credits. Apps and pages call your server (or a serverless function), and that calls the API. The only key that may appear in a page is a publishable pk_ key, and it only works for widget capabilities from the domains you allow. See key restrictions.

Web frameworks

React, Vue.js, Angular, Svelte: for a ready-made panel, use a widget: add the script once and a div where the panel goes. For anything else, call your own backend from the component.

Next.js, Nuxt, NestJS, Node.js: call the API from server code (a route handler, a server route, a controller), never from client components. A Next.js route handler:

app/api/chart/route.ts
export async function POST(request: Request) {
  const birth = await request.json(); // { datetime, timezone, latitude, longitude }
  const res = await fetch("https://api.96astroapi.com/v1/vedic-charts/planet-positions", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.ASTRO_API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify(birth),
  });
  return Response.json(await res.json(), { status: res.status });
}

In Nuxt the same code goes in server/api/chart.post.ts (defineEventHandler with readBody); in NestJS, in a controller method. The TypeScript SDK adds typed methods, retries and idempotency keys on top.

Mobile apps

Swift (iOS), Android and Kotlin, Flutter, React Native, Expo: the app sends the birth details to your backend or a serverless function (below), which adds the secret key and calls the API. The app never holds the key.

Swift
var request = URLRequest(url: URL(string: "https://your-backend.example.com/api/chart")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try JSONSerialization.data(withJSONObject: [
  "datetime": "1990-10-18T14:30:00", "timezone": "Asia/Kolkata", "latitude": 28.6139, "longitude": 77.209,
])
let (data, _) = try await URLSession.shared.data(for: request)
Flutter (package:http)
final res = await http.post(
  Uri.parse('https://your-backend.example.com/api/chart'),
  headers: {'Content-Type': 'application/json'},
  body: jsonEncode({'datetime': '1990-10-18T14:30:00', 'timezone': 'Asia/Kolkata', 'latitude': 28.6139, 'longitude': 77.209}),
);
final chart = jsonDecode(res.body);

On Android (Kotlin) the same request goes through OkHttp, Ktor or Retrofit; in React Native and Expo, through fetch. Protect your backend route as you protect the rest of your app (signed-in users only), so strangers cannot spend your credits through it.

Server languages

Python and Django, PHP and Laravel have SDKs (Python, PHP), and the PHP SDK includes a Laravel service provider. Without the SDK, Laravel's HTTP client is enough:

Laravel
$res = Http::withToken(config('services.astro96.key'))
    ->post('https://api.96astroapi.com/v1/vedic-charts/planet-positions', [
        'datetime' => '1990-10-18T14:30:00', 'timezone' => 'Asia/Kolkata',
        'latitude' => 28.6139, 'longitude' => 77.209,
    ]);
$sign = $res->json('data.ascendant.sign');

Go, Java and Spring, .NET, Ruby, Rust use their standard HTTP clients:

Go
body := strings.NewReader(`{"datetime":"1990-10-18T14:30:00","timezone":"Asia/Kolkata","latitude":28.6139,"longitude":77.209}`)
req, _ := http.NewRequest("POST", "https://api.96astroapi.com/v1/vedic-charts/planet-positions", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("ASTRO_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
Java 11+ (Spring works the same with RestClient or WebClient)
var request = HttpRequest.newBuilder(URI.create("https://api.96astroapi.com/v1/vedic-charts/planet-positions"))
    .header("Authorization", "Bearer " + System.getenv("ASTRO_API_KEY"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(json))
    .build();
var response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
.NET (C#)
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("ASTRO_API_KEY"));
var res = await http.PostAsync("https://api.96astroapi.com/v1/vedic-charts/planet-positions",
    new StringContent(json, Encoding.UTF8, "application/json"));
var body = await res.Content.ReadAsStringAsync();
Ruby (Rails works the same)
require "net/http"
require "json"

uri = URI("https://api.96astroapi.com/v1/vedic-charts/planet-positions")
birth = { datetime: "1990-10-18T14:30:00", timezone: "Asia/Kolkata", latitude: 28.6139, longitude: 77.209 }
res = Net::HTTP.post(uri, birth.to_json,
                     "Authorization" => "Bearer #{ENV.fetch('ASTRO_API_KEY')}", "Content-Type" => "application/json")
puts JSON.parse(res.body).dig("data", "ascendant", "sign")
Rust (reqwest with the json feature, serde_json)
let chart: serde_json::Value = reqwest::Client::new()
    .post("https://api.96astroapi.com/v1/vedic-charts/planet-positions")
    .bearer_auth(std::env::var("ASTRO_API_KEY")?)
    .json(&serde_json::json!({
        "datetime": "1990-10-18T14:30:00", "timezone": "Asia/Kolkata", "latitude": 28.6139, "longitude": 77.209
    }))
    .send().await?
    .json().await?;

Serverless functions

A function is the simplest backend for a mobile app or a static site: it keeps the key in the platform's secret store.

Cloudflare Workers (wrangler secret put ASTRO_API_KEY)
export default {
  async fetch(request, env) {
    const res = await fetch("https://api.96astroapi.com/v1/vedic-charts/planet-positions", {
      method: "POST",
      headers: { Authorization: `Bearer ${env.ASTRO_API_KEY}`, "Content-Type": "application/json" },
      body: await request.text(),
    });
    return new Response(res.body, { status: res.status, headers: { "Content-Type": "application/json" } });
  },
};
Supabase Edge Functions (supabase secrets set ASTRO_API_KEY=...)
Deno.serve(async (req) => {
  const res = await fetch("https://api.96astroapi.com/v1/vedic-charts/planet-positions", {
    method: "POST",
    headers: { Authorization: `Bearer ${Deno.env.get("ASTRO_API_KEY")}`, "Content-Type": "application/json" },
    body: await req.text(),
  });
  return new Response(res.body, { status: res.status, headers: { "Content-Type": "application/json" } });
});
Firebase Cloud Functions (2nd gen)
import { onRequest } from "firebase-functions/v2/https";
import { defineSecret } from "firebase-functions/params";

const ASTRO_API_KEY = defineSecret("ASTRO_API_KEY");

export const chart = onRequest({ secrets: [ASTRO_API_KEY] }, async (req, res) => {
  const r = await fetch("https://api.96astroapi.com/v1/vedic-charts/planet-positions", {
    method: "POST",
    headers: { Authorization: `Bearer ${ASTRO_API_KEY.value()}`, "Content-Type": "application/json" },
    body: JSON.stringify(req.body),
  });
  res.status(r.status).json(await r.json());
});

Check who is calling before you forward (a Firebase or Supabase signed-in user, or your own token), so the function does not become a free door to your credits.

Website builders and stores

WordPress: use the plugin.

Shopify, Webflow, Wix: add widgets with a custom-code block (Shopify: a Custom Liquid section in the theme editor; Webflow: an Embed element; Wix: Embed code). Create a publishable key and list your shop or site domain under Allowed origins. Some builders run embedded code inside their own frame, so the request comes from the builder's embed domain rather than yours: if a widget answers origin_not_allowed, open the browser's developer tools, look at the request's Origin header in the Network tab and add that domain to the key.

For anything beyond the widgets (reports, AI readings, your own layout), call the API from a serverless function as above and show its answer on the page.

Automation and testing

Zapier: use Webhooks by Zapier with Custom Request: method POST, the capability URL, data as JSON, and the headers Authorization: Bearer sk_live_... and Content-Type: application/json. The response fields are then available to the next steps of the Zap.

Postman: import the Postman collection, with sandbox and live environments.

AI assistants and agents (Claude, ChatGPT, Cursor): connect the MCP server.

On this page