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.
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.
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
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
Open a session
POST /api/v2/partner/ai/chat/startwith the user's birth fields (or/match-startwithperson1andperson2objects). Server computes the chart, returnssession_idplus an opening greeting from the astrologer. - 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
Send each user message
POST /api/v2/partner/ai/chat/messagewith thesession_idand the user's message. Server pulls history, calls the astrologer, returns the reply in the same shape. Two-chart sessions use the same/messageendpoint — the session knows which mode it's in. - 4
Track billing per turn
Each successful turn is debited from your account automatically. The
billingblock on each response tells you what was charged and the remaining balance. Failed turns are not charged.
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();
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 clientdart:convert— JSON (built-in)- No platform-specific permissions needed
- Works identically on Android, iOS, web, desktop
📱iOS native (Swift)
Native Foundation frameworks only.
URLSession— RESTJSONDecoder/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— RESTcom.squareup.moshi:moshiorgson— JSONINTERNETpermission 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+) oraxios - Python:
requestsorhttpx - Go:
net/http+encoding/json - Java:
HttpClient+ Jackson or OkHttp - PHP:
curl+json_decode - Ruby:
net/http+json
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.
// 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..."
}
}
// 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"
}
}
}
// 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 */ }
}
}
{
"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
Questions developers ask before integrating.
What makes this different from other chat astrologer APIs?
/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?
/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?
When do I use /start vs /match-start?
/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?
How fast are replies?
Where is conversation history stored?
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?
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?
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?
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