Authentication
Every request carries your secret key in the x-api-key header (format ajk_<12 hex>_<40 hex>). Create and revoke keys on the APIs page after logging in with your mobile number — the same account and wallet as the Apna AI Pandit app. The full key is shown only once; we store only a hash. Keep keys on your server, never in a mobile app or browser.
Create a report
POST https://apnaaipandit.com/api/v1/public/reports/{reportType}
Content-Type: application/json
x-api-key: ajk_…
Idempotency-Key: order-1001 (optional, recommended)
Synchronous: JSON reports return in ~0.3–1.5 s, PDFs in ~3–8 s (~26 dense pages). Use a client timeout of 120 s.
Report types
| Report | reportType | Languages | Pages | Price / report | Sample |
|---|---|---|---|---|---|
| Complete Kundli Full birth-chart report (~26 dense A4 pages): basic details, avakahada chakra, D1/D9 charts (North + South), planetary positions with planet images, all 16 divisional charts, planetary friendship, aspects, KP planet lords, ascendant, main areas of life, Moon sign & nakshatra, birth panchang, planets in houses and in signs, house results, yogas, doshas, Vimshottari maha / antar / pratyantar with mahadasha predictions, Yogini and Chara dasha, Sade Sati, Ashtakavarga, Shadbala, Lal Kitab with 35-year dasha, remedies. | complete_kundli | hi, en | ~26 | ₹99 | |
| Kundli (basic) Short birth-chart report: basic details, charts, planetary positions, ascendant, Moon sign & nakshatra, yogas, doshas, Vimshottari dasha. | kundli_basic | hi, en | ~6 | ₹29 | |
| Yearly forecast Forecast for the next 12 months from today: running antardashas with dates, Saturn / Jupiter / Rahu transits from the Moon sign, Sade Sati / Dhaiya, remedies. | yearly | hi, en | ~5 | ₹79 | |
| Career report 10th and 6th houses and their lords, planets there, significators (Sun, Saturn, Mercury), career yogas, dasha timeline, remedies. | topic_career | hi, en | ~6 | ₹49 | |
| Marriage report 7th and 2nd houses, Venus and Jupiter, navamsa chart, Manglik and related yogas, dasha timeline, remedies. | topic_marriage | hi, en | ~6 | ₹49 | |
| Finance report 2nd and 11th houses, Jupiter and Venus, dhana yogas, dasha timeline, remedies. Not investment advice. | topic_finance | hi, en | ~6 | ₹49 | |
| Health report Ascendant and 6th house, Sun and Moon, vitality-related yogas, dasha timeline, remedies. Not medical advice. | topic_health | hi, en | ~6 | ₹49 | |
| Education report 4th and 5th houses, Mercury and Jupiter, learning yogas, dasha timeline, remedies. | topic_education | hi, en | ~6 | ₹49 |
Request body
| Field | Type | Notes |
|---|---|---|
birth.date | string | Local birth date YYYY-MM-DD (required) |
birth.time | string | Local time HH:mm or HH:mm:ss, 24-hour (required) |
birth.timezone | string | IANA zone, e.g. Asia/Kolkata. Historical offsets / DST handled (required) |
birth.latitude / longitude | number | Decimal degrees, north / east positive (required) |
language | "hi" | "en" | Report language (required) |
name, place | string ≤ 80 | Printed on the cover (optional) |
format | "json" | "pdf" | "both" | Default json. PDFs are generated and stored on our server and returned as a signed download URL |
pdfDelivery | "url" | "base64" | Default url. base64 additionally puts the PDF inside the JSON (large responses) |
branding | object | White-label PDF (optional) — see below |
{
"birth": {
"date": "1990-01-15",
"time": "10:30",
"timezone": "Asia/Kolkata",
"latitude": 28.6139,
"longitude": 77.2090
},
"language": "en",
"name": "Sample User",
"place": "New Delhi",
"format": "pdf",
"branding": {
"brandName": "Your Brand Astrology",
"primaryColor": "#0b5394",
"accentColor": "#e69138",
"contact": { "phone": "+91 90000 00000", "website": "yourbrand.example" },
"footerText": "Consult our astrologers for remedies"
}
}
White-label branding
Set a default brand once on the APIs page; any request can override it field by field. With a brandName, the PDF shows only your brand — our name and engine versions are hidden.
| Field | Rules |
|---|---|
brandName | ≤ 60 characters, on the cover and footer |
primaryColor, accentColor | #RRGGBB — section headers, tables, charts, cover |
logoDataUri | data:image/png;base64,… or JPEG, ≤ 90 000 characters (≈ 65 KB). URLs and SVG are not accepted |
contact.phone / email / website / address | Printed on the cover |
footerText | ≤ 160 characters |
showVersions | true = print engine version line (default false for brands) |
Response
HTTP 200
{
"success": true,
"data": {
"requestId": "8ced4456-f82b-44d0-a57a-8c3e77a33ea5",
"charged": 99,
"walletBalance": 901,
"reportType": "complete_kundli",
"language": "en",
"title": "Complete Kundli",
"versions": { "calc": "calc-2.2.0", "conventions": "conv-1.1.0", "rules": "rules-1.0.0", "hooks": "hooks-1.4.0", "composer": "composer-1.1.0", "blueprint": "complete_kundli@3" },
"coverage": 1,
"generatedAt": "2026-10-08T10:30:00.000Z",
"toc": [ { "id": "basic", "number": 1, "title": "Basic details" }, … ], // json / both
"sections": [ { "id": "basic", "title": "…", "blocks": [ … ] }, … ], // json / both
"pdfUrl": "https://…/api/v1/public/files/8ced4456-….pdf?e=1760000000&s=…", // pdf / both — signed, no key needed
"pdfExpiresAt": "2026-10-15T10:30:00.000Z", "pdfPages": 26, "pdfBytes": 652144
}
}
Download again later
The PDF stays on our server for 30 days. Give the pdfUrl directly to your customer, or fetch a fresh link any time:
GET /api/v1/public/reports/{requestId} (x-api-key)
→ 200 { requestId, reportType, language, format, charged, createdAt, pdfAvailable, pdf: { pdfUrl, pdfExpiresAt, pdfPages, pdfBytes } }
Each request id is also listed with a Download link on your APIs page. Links are signed and expire (default 7 days); a changed or expired link returns 404.
Blocks are typed: paragraph, heading (optional icon = planet id and chips = short facts such as house / sign / dignity), table (optional compact, highlight = running-period rows), kv-grid, chart (house → sign + planets; size: "small" for divisional charts), grid (columns + items = small tables / charts side by side), planet-cards, timeline, callout — render them in your own UI, or use the PDF. Unknown block types may be added later: skip what you do not render.
Billing & wallet
- Each successful report is charged at the catalog price from your Apna AI Pandit wallet (the same wallet as chat in the app). The response shows
chargedandwalletBalance. - Low balance →
402 INSUFFICIENT_BALANCE, nothing charged. Recharge in the Apna AI Pandit app. - Any failure after charging (content unavailable, PDF error, server error) is refunded automatically.
- Usage, spend and every request id are on the APIs page.
Idempotency
Send Idempotency-Key (your order id, 1–64 characters [A-Za-z0-9_.:-]). A repeat with the same key within 24 h returns 409 DUPLICATE_REQUEST with the first request id instead of charging again. If the first request failed, the key is released and you may retry with it.
Limits
- Per-minute requests and monthly reports per account (defaults 30 / min and 1 000 / month — ask support to raise).
- Request body ≤ 100 KB. PDFs are rendered with limited parallelism; busy →
503 PDF_BUSY(refunded), retry with back-off. - Up to 5 active keys per account.
Errors
All errors use one envelope: { "success": false, "data": null, "error": { "code": "…", "message": "…" } }
| HTTP | code | Meaning |
|---|---|---|
| 400 | VALIDATION_ERROR | Body field missing / wrong format (message lists the fields) |
| 400 | INVALID_BIRTH_DATA | Impossible date / time, unknown IANA timezone, bad coordinates |
| 400 | INVALID_IDEMPOTENCY_KEY | Idempotency-Key is not 1–64 characters [A-Za-z0-9_.:-] |
| 401 | INVALID_API_KEY | Missing, malformed, wrong or revoked x-api-key |
| 402 | INSUFFICIENT_BALANCE | Wallet balance below the report price — recharge the account (nothing was charged) |
| 403 | CLIENT_SUSPENDED | API account suspended by support |
| 403 | ACCOUNT_INACTIVE / ACCOUNT_NOT_LINKED | The app account behind the key is blocked / missing |
| 403 | REPORT_TYPE_NOT_ALLOWED / REPORT_TYPE_DISABLED | Report type not enabled for your account / currently not offered |
| 404 | UNKNOWN_REPORT_TYPE | reportType in the URL is not in the catalog |
| 409 | DUPLICATE_REQUEST | Same Idempotency-Key already used in the last 24 h (message has the first requestId) |
| 413 | PAYLOAD_TOO_LARGE | Request body over 100 KB (usually a large logo) |
| 429 | RATE_LIMITED | Per-minute limit of your account exceeded |
| 429 | QUOTA_EXCEEDED | Monthly report quota of your account used |
| 429 | TOO_MANY_FAILED_ATTEMPTS | Too many failed authentications from your IP this minute |
| 503 | REPORT_NOT_AVAILABLE | Report content for this language is being updated — retry later (refunded) |
| 503 | PDF_BUSY | PDF capacity busy — retry in a minute (refunded) |
| 500 | INTERNAL_ERROR | Unexpected error (refunded) — contact support with the requestId |
Code examples
curl -X POST "https://apnaaipandit.com/api/v1/public/reports/complete_kundli" \
-H "Content-Type: application/json" \
-H "x-api-key: $API_KEY" \
-H "Idempotency-Key: order-1001" \
-d '{"birth":{"date":"1990-01-15","time":"10:30","timezone":"Asia/Kolkata","latitude":28.6139,"longitude":77.209},"language":"en","format":"pdf","branding":{"brandName":"Your Brand"}}' \
| jq -r '.data.pdfUrl' | xargs curl -s -o report.pdf # signed link, valid 7 days<?php
$body = [
'birth' => ['date' => '1990-01-15', 'time' => '10:30', 'timezone' => 'Asia/Kolkata', 'latitude' => 28.6139, 'longitude' => 77.209],
'language' => 'en', 'format' => 'pdf',
'branding' => ['brandName' => 'Your Brand', 'primaryColor' => '#0b5394'],
];
$ch = curl_init('https://apnaaipandit.com/api/v1/public/reports/complete_kundli');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'x-api-key: ' . getenv('API_KEY'), 'Idempotency-Key: order-1001'],
CURLOPT_POSTFIELDS => json_encode($body),
CURLOPT_TIMEOUT => 120,
]);
$res = json_decode(curl_exec($ch), true);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code !== 200) { throw new Exception($res['error']['code'] . ': ' . $res['error']['message']); }
// PDF is generated on our server — download it (or give $res['data']['pdfUrl'] to your customer; valid 7 days)
file_put_contents('report.pdf', file_get_contents($res['data']['pdfUrl']));
echo 'Charged ₹' . $res['data']['charged'] . ', balance ₹' . $res['data']['walletBalance'];import base64, os, requests
body = {
"birth": {"date": "1990-01-15", "time": "10:30", "timezone": "Asia/Kolkata", "latitude": 28.6139, "longitude": 77.209},
"language": "en", "format": "pdf",
"branding": {"brandName": "Your Brand", "primaryColor": "#0b5394"},
}
r = requests.post(
"https://apnaaipandit.com/api/v1/public/reports/complete_kundli",
json=body,
headers={"x-api-key": os.environ["API_KEY"], "Idempotency-Key": "order-1001"},
timeout=120,
)
res = r.json()
if r.status_code != 200:
raise RuntimeError(f"{res['error']['code']}: {res['error']['message']}")
# PDF is generated on our server: download it, or hand res["data"]["pdfUrl"] to your customer (signed, valid 7 days)
open("report.pdf", "wb").write(requests.get(res["data"]["pdfUrl"], timeout=60).content)
print("charged", res["data"]["charged"], "balance", res["data"]["walletBalance"])// Node 18+ (built-in fetch)
import { writeFile } from 'node:fs/promises';
const r = await fetch('https://apnaaipandit.com/api/v1/public/reports/complete_kundli', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.API_KEY, 'Idempotency-Key': 'order-1001' },
body: JSON.stringify({
birth: { date: '1990-01-15', time: '10:30', timezone: 'Asia/Kolkata', latitude: 28.6139, longitude: 77.209 },
language: 'en',
format: 'pdf',
branding: { brandName: 'Your Brand', primaryColor: '#0b5394' },
}),
});
const res = await r.json();
if (!r.ok) throw new Error(`${res.error.code}: ${res.error.message}`);
// PDF is generated on our server: download it, or give res.data.pdfUrl to your customer (signed, valid 7 days)
await writeFile('report.pdf', Buffer.from(await (await fetch(res.data.pdfUrl)).arrayBuffer()));
console.log('charged', res.data.charged, 'balance', res.data.walletBalance);
Privacy
Birth details are used only to build the report: we do not store them in usage logs (only a one-way hash and the request id). Generated reports are not stored by the API — save the response on your side. Calculations follow the Lahiri (Chitrapaksha) ayanamsa; reports are guidance for self-reflection, not medical, legal or financial advice.