An AI chat astrologer for one chart, or two.

Production-grade AI chat astrologer API. Real birth charts, real dasha and transit context, multi-turn conversations. The only AI chat astrologer API with native two-chart sessions for kundli matching and compatibility consultations.

2
Session modes
REST
+ JSON
3
Endpoints
Multi
lingual
One of a kind

The only AI chat astrologer API that holds two birth charts in one conversation.

Every other AI chat astrologer API does one chart per session. Ours does one or two. Single-chart sessions for career, life, transits, daily questions. Two-chart sessions for kundli matching, synastry, and any relationship conversation where the astrologer needs both partners' charts in view simultaneously.

Single-chart sessions

One person's chart in scope. Career, life direction, transits, dasha timing, daily and weekly guidance, decision-making.

Two-chart sessions

Both partners' charts loaded together. Native Ashtakoot kundli matching, synastry, Manglik analysis, relationship counsel — all in one ongoing chat.

Chart-grounded, every turn

Real planetary positions, ascendant, dasha periods, active transits — computed and cached at session start. The astrologer cannot invent placements.

What it offers astrologically

Real chart analysis, not horoscope clichés.

Every conversation sits on a real birth chart computed with Swiss Ephemeris precision. The astrologer draws on classical Vedic methodology, with depth across KP, Lal Kitab, Jaimini, and Western evolutionary frameworks. Topics covered are as broad as a real consultation — relationships, career, finance, health, family, and life timing.

𑖀Vedic Jyotish (Parashari)

Classical D-1 birth chart analysis. Houses, lordships, exaltation and debilitation, yogas, conjunctions, aspects, divisional charts (D-9 navamsa, D-10 dasamsa, D-7, D-60). The default backbone of the astrologer's reasoning.

Dasha & transit timing

Live Vimshottari Mahadasha and Antardasha at the moment of the question, plus active transits and sade sati / kantaka shani / ashtama shani. Career, marriage, and major-decision questions get real timing windows, not vague months.

KP (Krishnamurti Paddhati)

Sub-lord precision for timing-sensitive questions. Ruling planets, significators, cuspal sub-lord theory — applied when the conversation calls for it (job-change date, surgery timing, exam outcome).

Lal Kitab remedies

Plain-spoken remedial guidance when users ask "what should I do." Houses, planetary conditions, and practical remedies that respect tradition without being prescriptive about anything that affects health or major life decisions.

Two-chart matching

Native Ashtakoot Gun Milan (8 kootas, 36-point scale), Manglik analysis with cancellation rules, beeja-kshetra, divisional comparison, house overlay. Compatibility chat goes beyond a score — the astrologer can explain why and what to watch for.

Western & numerology

Evolutionary western framing for psychological depth (chosen lessons, archetypal patterns). Pythagorean and Chaldean numerology for name and date analysis. Available as complementary lenses when the conversation suits them.

Topics covered

  • Career, profession, promotion timing
  • Marriage, partner compatibility, matchmaking
  • Love, dating, relationship dynamics
  • Finance, wealth, investment timing
  • Health and wellbeing direction
  • Family, children, parenting questions
  • Education and career-path decisions
  • Transit timing for major decisions
  • Dasha-period guidance and remedies

What's off-topic

The astrologer stays on astrology. Off-topic requests — coding help, general knowledge, news, medical diagnosis, legal advice, financial trading recommendations — are politely declined. This keeps responses focused and predictable for your users.

Medical, legal, and financial topics are discussed in chart-context terms only ("favourable period for surgery decisions" rather than "you have condition X"). The astrologer recommends professional consultation for anything beyond chart guidance.

Reply quality

  • Typical response: 1.5–3 seconds
  • First message of session: 3–5 seconds
  • Pre-split into reading-sized chunks
  • Suggested follow-up prompts included
  • Multilingual switching mid-conversation
  • No off-topic drift, no generic horoscope fluff
How to integrate

Three endpoints. JSON in, JSON out.

Authenticate with the X-Api-Key header on every request. Open a session with /start (single chart) or /match-start (two charts). Then keep calling /message with the session_id for follow-up turns. Server holds the chart and the conversation history under the session ID — your client only sends the next message.

  1. 1

    Open a session

    POST /api/v2/partner/ai/chat/start with the user's birth fields (or /match-start with person1 and person2 objects). Server computes the chart, returns session_id plus an opening greeting from the astrologer.

  2. 2

    Render the opening greeting

    The response contains data.new_messages[0].message — an array of text chunks. Render each chunk as its own message bubble, optionally with a short delay between them for a natural reading rhythm. Also surfaced: suggested_followups — quick-reply prompts you can offer the user.

  3. 3

    Send each user message

    POST /api/v2/partner/ai/chat/message with the session_id and the user's message. Server pulls history, calls the astrologer, returns the reply in the same shape. Two-chart sessions use the same /message endpoint — the session knows which mode it's in.

  4. 4

    Track billing per turn

    Each successful turn is debited from your account automatically. The billing block on each response tells you what was charged and the remaining balance. Failed turns are not charged.

Code snippets

Drop-in code for any stack.

Single-chart session flow shown below. Two-chart flow is identical except you POST to /match-start and the body has person1 and person2 objects instead of flat birth fields. All subsequent turns use the same /message endpoint.

# Step 1 — open a single-chart session
curl -X POST https://starsapi.com/api/v2/partner/ai/chat/start \
  -H "X-Api-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "astrologer":  "guruji",
    "year": 1990, "month": 6, "day": 15,
    "hour": 14,   "minute": 30,
    "timezone": "Asia/Kolkata",
    "latitude":   28.6139, "longitude": 77.2090,
    "name":  "Ravi",
    "gender":"male",
    "preferred_language":   "en"
  }'

# Response contains data.session_id and the opening greeting in
# data.new_messages[0].message (array of text chunks).

# Step 2 — every subsequent turn
curl -X POST https://starsapi.com/api/v2/partner/ai/chat/message \
  -H "X-Api-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "abc123def456abc123def456abc12345",
    "message":    "Will I get the promotion this year?"
  }'
const BASE    = "https://starsapi.com/api/v2/partner/ai/chat";
const headers = { "X-Api-Key": API_KEY, "Content-Type": "application/json" };

// Step 1 — open the session
const start = await fetch(`${BASE}/start`, {
  method:  "POST",
  headers,
  body: JSON.stringify({
    astrologer:  "guruji",
    year: 1990, month: 6, day: 15, hour: 14, minute: 30, timezone: "Asia/Kolkata",
    latitude: 28.6139, longitude: 77.2090,
    name: "Ravi", gender: "male",
    preferred_language: "en",
  }),
}).then(r => r.json());

const sessionId = start.data.session_id;
for (const chunk of start.data.new_messages[0].message) {
  renderBubble({ role: "astrologer", text: chunk });
}

// Step 2 — send a user message
async function sendMessage(text) {
  const r = await fetch(`${BASE}/message`, {
    method: "POST",
    headers,
    body: JSON.stringify({ session_id: sessionId, message: text }),
  }).then(r => r.json());

  for (const chunk of r.data.new_messages[0].message) {
    renderBubble({ role: "astrologer", text: chunk });
  }
  return r.data;
}
import 'package:http/http.dart' as http;
import 'dart:convert';

const BASE = 'https://starsapi.com/api/v2/partner/ai/chat';
final headers = {
  'X-Api-Key':    API_KEY,
  'Content-Type': 'application/json',
};

// Step 1 — open the session
final startResp = await http.post(
  Uri.parse('$BASE/start'),
  headers: headers,
  body: jsonEncode({
    'astrologer':  'guruji',
    'year': 1990, 'month': 6, 'day': 15,
    'hour': 14,   'minute': 30, 'timezone': 'Asia/Kolkata',
    'latitude':   28.6139, 'longitude': 77.2090,
    'name':  'Ravi',
    'gender':'male',
    'preferred_language':   'en',
  }),
);
final start = jsonDecode(startResp.body)['data'];
final sessionId = start['session_id'];
for (final chunk in start['new_messages'][0]['message']) {
  addBubble(role: 'astrologer', text: chunk);
}

// Step 2 — send a user message
Future<Map> sendMessage(String text) async {
  final r = await http.post(
    Uri.parse('$BASE/message'),
    headers: headers,
    body: jsonEncode({ 'session_id': sessionId, 'message': text }),
  );
  return jsonDecode(r.body)['data'];
}
import requests

BASE    = "https://starsapi.com/api/v2/partner/ai/chat"
HEADERS = { "X-Api-Key": API_KEY, "Content-Type": "application/json" }

# Step 1 — open the session
start = requests.post(f"{BASE}/start", headers=HEADERS, json={
    "astrologer":  "guruji",
    "year": 1990, "month": 6, "day": 15,
    "hour": 14,   "minute": 30, "timezone": "Asia/Kolkata",
    "latitude":   28.6139, "longitude": 77.2090,
    "name":  "Ravi",
    "gender":"male",
    "preferred_language":   "en",
}).json()

session_id = start["data"]["session_id"]
for chunk in start["data"]["new_messages"][0]["message"]:
    render_bubble(role="astrologer", text=chunk)

# Step 2 — every subsequent turn
def send_message(text: str) -> dict:
    r = requests.post(f"{BASE}/message", headers=HEADERS, json={
        "session_id": session_id,
        "message":    text,
    }).json()
    for chunk in r["data"]["new_messages"][0]["message"]:
        render_bubble(role="astrologer", text=chunk)
    return r["data"]
import java.net.URI;
import java.net.http.*;
import java.net.http.HttpRequest.BodyPublishers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import java.util.Map;

static final String BASE   = "https://starsapi.com/api/v2/partner/ai/chat";
static final HttpClient C  = HttpClient.newHttpClient();
static final ObjectMapper M = new ObjectMapper();

// Step 1 — open the session
String startBody = M.writeValueAsString(Map.of(
    "astrologer", "guruji",
    "year", 1990, "month", 6, "day", 15,
    "hour", 14,   "minute", 30, "timezone", 5.5,
    "latitude", 28.6139, "longitude", 77.2090,
    "name", "Ravi", "gender", "male",
    "preferred_language", "en"
));
HttpResponse<String> startResp = C.send(
    HttpRequest.newBuilder(URI.create(BASE + "/start"))
        .header("X-Api-Key",    API_KEY)
        .header("Content-Type", "application/json")
        .POST(BodyPublishers.ofString(startBody)).build(),
    HttpResponse.BodyHandlers.ofString());
JsonNode start = M.readTree(startResp.body()).get("data");
String sessionId = start.get("session_id").asText();

// Step 2 — send a user message
String msgBody = M.writeValueAsString(Map.of(
    "session_id", sessionId,
    "message",    "Will I get the promotion this year?"
));
HttpResponse<String> msgResp = C.send(
    HttpRequest.newBuilder(URI.create(BASE + "/message"))
        .header("X-Api-Key",    API_KEY)
        .header("Content-Type", "application/json")
        .POST(BodyPublishers.ofString(msgBody)).build(),
    HttpResponse.BodyHandlers.ofString());
JsonNode reply = M.readTree(msgResp.body()).get("data");
for (JsonNode chunk : reply.get("new_messages").get(0).get("message")) {
    System.out.println("Astrologer: " + chunk.asText());
}
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

const base = "https://starsapi.com/api/v2/partner/ai/chat"

func post(path string, body any) (map[string]any, error) {
    b, _ := json.Marshal(body)
    req, _ := http.NewRequest("POST", base+path, bytes.NewReader(b))
    req.Header.Set("X-Api-Key",    apiKey)
    req.Header.Set("Content-Type", "application/json")
    resp, err := http.DefaultClient.Do(req)
    if err != nil { return nil, err }
    defer resp.Body.Close()
    var out map[string]any
    json.NewDecoder(resp.Body).Decode(&out)
    return out, nil
}

func main() {
    // Step 1 — open the session
    start, _ := post("/start", map[string]any{
        "astrologer":  "guruji",
        "year": 1990, "month": 6, "day": 15,
        "hour": 14, "minute": 30, "timezone": "Asia/Kolkata",
        "latitude": 28.6139, "longitude": 77.2090,
        "name": "Ravi", "gender": "male",
        "preferred_language": "en",
    })
    data := start["data"].(map[string]any)
    sessionId := data["session_id"].(string)
    for _, chunk := range data["new_messages"].([]any)[0].(map[string]any)["message"].([]any) {
        renderBubble("astrologer", chunk.(string))
    }

    // Step 2 — send a user message
    reply, _ := post("/message", map[string]any{
        "session_id": sessionId,
        "message":    "Will I get the promotion this year?",
    })
    _ = reply
}
// Requires cpprestsdk or libcurl + a JSON library (nlohmann/json).
// Example using cpprestsdk.

#include <cpprest/http_client.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::client;

const auto BASE = U("https://starsapi.com/api/v2/partner/ai/chat");

// Step 1 — open the session
http_client client(BASE);
json::value startBody;
startBody[U("astrologer")]   = json::value::string(U("guruji"));
startBody[U("year")]         = 1990;
startBody[U("month")]        = 6;
startBody[U("day")]          = 15;
startBody[U("hour")]         = 14;
startBody[U("minute")]       = 30;
startBody[U("timezone")]     = 5.5;
startBody[U("latitude")]     = 28.6139;
startBody[U("longitude")]    = 77.2090;
startBody[U("name")]    = json::value::string(U("Ravi"));
startBody[U("gender")]  = json::value::string(U("male"));
startBody[U("preferred_language")]     = json::value::string(U("en"));

http_request req(methods::POST);
req.set_request_uri(U("/start"));
req.headers().add(U("X-Api-Key"),    U(API_KEY));
req.headers().add(U("Content-Type"), U("application/json"));
req.set_body(startBody);
auto resp = client.request(req).get();
auto j    = resp.extract_json().get();
auto sid  = j[U("data")][U("session_id")].as_string();

// Step 2 — send a user message
json::value msgBody;
msgBody[U("session_id")] = json::value::string(sid);
msgBody[U("message")]    = json::value::string(U("Will I get the promotion this year?"));

http_request msg(methods::POST);
msg.set_request_uri(U("/message"));
msg.headers().add(U("X-Api-Key"),    U(API_KEY));
msg.headers().add(U("Content-Type"), U("application/json"));
msg.set_body(msgBody);
auto reply = client.request(msg).get().extract_json().get();
Platform requirements

Libraries you need on each platform.

Chat is REST + JSON over HTTPS. Every modern platform has HTTP and JSON natively. Below is the recommended HTTP client per stack — nothing more is needed. No SDK, no proprietary client library, no audio dependencies.

🌐Web / Browser

Native fetch + JSON.parse. Zero dependencies.

  • Any modern browser (Chrome, Safari, Firefox, Edge)
  • CORS is enabled on all partner endpoints
  • No build step required

🎯Flutter / Dart

One pub.dev package.

  • http: ^1.0.0 — REST client
  • dart:convert — JSON (built-in)
  • No platform-specific permissions needed
  • Works identically on Android, iOS, web, desktop

📱iOS native (Swift)

Native Foundation frameworks only.

  • URLSession — REST
  • JSONDecoder/JSONEncoder — JSON
  • No third-party dependencies
  • Minimum iOS 12 (no special requirement)

🤖Android native (Kotlin / Java)

Standard Android networking stack.

  • com.squareup.okhttp3:okhttp:4.x — REST
  • com.squareup.moshi:moshi or gson — JSON
  • INTERNET permission in manifest (default)
  • Compatible with any minSdk ≥ 21

React Native

Native runtime — nothing to install.

  • fetch + JSON.parse (native)
  • Same code runs on iOS and Android
  • No native modules required

Server-side

Anything with HTTP + JSON.

  • Node: native fetch (Node 18+) or axios
  • Python: requests or httpx
  • Go: net/http + encoding/json
  • Java: HttpClient + Jackson or OkHttp
  • PHP: curl + json_decode
  • Ruby: net/http + json
Payload & response

Exact wire format.

All endpoints accept POST JSON and return { "success", "timestamp", "response_time_ms", "data": {...} }. Errors return { "success": false, "error": { "code", "message" } } with an appropriate HTTP status.

POST /api/v2/partner/ai/chat/start — single-chart session
// Request
{
  "astrologer":  "guruji",       // astrologer key (default: "guruji")
  "year": 1990, "month": 6, "day": 15,    // birth date
  "hour": 14,   "minute": 30,             // birth time, 24h
  "timezone": "Asia/Kolkata",            // hours from UTC, e.g. 5.5 for IST
  "latitude":   28.6139,
  "longitude":  77.2090,
  "name":   "Ravi",         // optional
  // optional, auto-computed if absent
  "gender": "male",         // optional
  "preferred_language":    "en"            // optional, ISO 639-1 code
}

// Response
{
  "success": true,
  "timestamp": "2026-05-17T13:45:00+00:00",
  "response_time_ms": 4231,
  "data": {
    "session_id": "abc123def456abc123def456abc12345",
    "turn":       1,
    "astrologer": {
      "key":              "guruji",
      "name":             "Guruji",
      "avatar_emoji":     "🙏",
      "astrology_system": "vedic"
    },
    "new_messages": [
      { "role": "assistant",
        "message": [
          "Namaste Ravi. Your chart shows Cancer ascendant with Moon in Aquarius...",
          "Right now Saturn is transiting your 4th house. What's on your mind?"
        ]
      }
    ],
    "suggested_followups": [
      "How is my career looking this year?",
      "What does my current dasha tell us?"
    ],
    "billing":     { /* wallet info */ },
    "pre_message": "Guruji is studying your chart..."
  }
}
POST /api/v2/partner/ai/chat/match-start — two-chart compatibility session
// Request
{
  "astrologer": "guruji",
  "preferred_language": "hi",
  "person1": {
    "name":      "Raj",          "gender":  "male",
    "year":      1990, "month":  6,  "day":    15,
    "hour":      10,   "minute": 30,
    "latitude":  28.6139, "longitude": 77.2090,
    "timezone":  "Asia/Kolkata"
  },
  "person2": {
    "name":      "Priya",        "gender":  "female",
    "year":      1992, "month":  8,  "day":    22,
    "hour":      14,   "minute": 45,
    "latitude":  19.0760, "longitude": 72.8777,
    "timezone":  "Asia/Kolkata"
  }
}

// Response — same shape as /start, plus match_summary
{
  "success": true,
  "data": {
    "session_id": "xyz789...",
    "turn":       1,
    "astrologer": { "key": "guruji", "name": "...", ... },
    "new_messages": [
      { "role": "assistant",
        "message": ["Raj and Priya — looking at your charts...", "..."] }
    ],
    "suggested_followups": [ ... ],
    "billing":     { ... },
    "match_summary": {
      "total_points": 32,
      "max_points":   36,
      "percentage":   88.9,
      "verdict":      "Excellent match"
    }
  }
}
POST /api/v2/partner/ai/chat/message — any session type
// Request — just three fields
{
  "session_id": "abc123def456abc123def456abc12345",
  "message":    "Will I get the promotion this year?"
}

// Response — pre-chunked reply ready to render as bubbles
{
  "success": true,
  "data": {
    "session_id": "abc123...",
    "turn":       3,
    "astrologer": { ... },
    "new_messages": [
      { "role": "assistant",
        "message": [
          "Jupiter is currently transiting your 10th house...",
          "Combined with your Jupiter Mahadasha, this is a favourable promotion window."
        ]
      }
    ],
    "suggested_followups": [ ... ],
    "billing":             { /* debit info on this turn */ }
  }
}
Error envelope
{
  "success": false,
  "timestamp": "...",
  "error": {
    "code":    "SESSION_NOT_FOUND",
    "message": "Session not found"
  }
}

// Codes:
//   INVALID_JSON         400 — body not parseable
//   METHOD_NOT_ALLOWED   405 — only POST
//   AUTH_ERROR           401 — API key validation failed
//   VALIDATION_ERROR     400 — missing/invalid field
//   SESSION_NOT_FOUND    404 — session_id unknown
//   FORBIDDEN            403 — session belongs to a different API key
//   SESSION_CLOSED       409 — session marked inactive
//   CALCULATION_ERROR    500 — chart computation failed
//   AI_ERROR             502 — upstream reply failed; safe to retry
//   CONFIG_ERROR         500 — astrologer config not found
//   INTERNAL_ERROR       500 — unhandled server error
Frequently asked

Questions developers ask before integrating.

What makes this different from other chat astrologer APIs?
Two-chart sessions. Every other chat astrologer API does one chart per conversation. Our /match-start endpoint loads both partners' charts into one session, so users can ask the astrologer anything about their relationship and get answers grounded in both charts simultaneously. Native kundli matching, native synastry, native compatibility chat — uncontested in the category.
How is the chat grounded in the real birth chart?
When you call /start or /match-start, the server computes the full birth chart (or both charts for compatibility) — planetary positions, ascendant, dashas, divisional charts, current transits — and caches that summary against the session. Every reply from then on is built on that real astronomical data. The astrologer cannot invent planetary placements or timings.
What astrological systems are supported?
Vedic Jyotish in the Parashari tradition is the default, with depth in KP (Krishnamurti Paddhati) for timing-precision work, Lal Kitab for remedial guidance, Jaimini for arudhas and karakas, and Western evolutionary astrology for psychological framing. Numerology is available as a complementary system. The astrologer roster available on your API key is determined by your plan.
When do I use /start vs /match-start?
Use /start when the conversation is about one person — career, life direction, transits, daily questions, dasha guidance. Use /match-start when it's about two people — kundli matching, compatibility, relationship advice, marital questions. Once started, both session types use the same /message endpoint for follow-up turns.
What topics can users ask about?
Career and profession, marriage and matchmaking, love and relationships, finance and wealth, health and wellbeing, family and children, education, travel, spiritual practice, transit timing, dasha periods, remedies, and any chart-related question. The astrologer stays on astrology — it won't answer off-topic questions like coding or general knowledge.
How fast are replies?
Typical replies arrive in 1.5 to 3 seconds for ordinary turns. The first message of a session takes a little longer (3–5 seconds) because the chart is computed and the opening greeting is generated. The response comes back pre-split into natural reading-sized chunks, so you can render each chunk in a separate bubble for a typing-rhythm effect.
Where is conversation history stored?
Server-side, against the session ID. Your client doesn't need to manage history arrays — just send each new message with the session_id and the server stitches the full conversation context automatically. You're welcome to mirror history client-side for UI display, but the API doesn't require it.
Which languages are supported?
English, Hindi, Bengali, Tamil, Telugu, and others on request. Pass an optional language field on the start call to set the initial language. After that, whatever language the user types in wins — they can switch mid-conversation freely.
How is billing handled?
Per-turn from your account credits. Each successful turn is debited automatically — there's no separate billing endpoint or webhook to wire up. The billing block on each response tells you what was charged and what's left. Failed turns are not charged.
Can I white-label the chat?
Yes. There's no StarsAPI branding in any response. The astrologer's name, avatar, and reply are yours to display as your own product. Wallet balance and rate are returned numerically — display in whatever currency or credits-model you use.

Ship an AI chat astrologer this week.

One API key. Three endpoints. Real chart grounding. Native two-chart compatibility chat — uncontested in the category.

View pricing Talk to us