- Docs
- Domain Guides
- Chinese Astrology
Chinese Astrology API, what to build and how to call it
Ship a BaZi Four Pillars reader, a Chinese zodiac compatibility page, a lunar calendar converter, or a Tong Shu date picker in under 30 minutes. No BaZi training required.
Chinese astrology is a full domain in the RoxyAPI catalog. 16 endpoints covering BaZi (Four Pillars of Destiny), Day Master strength, luck pillars, annual forecast, the twelve-animal zodiac, the lunisolar calendar, the 24 solar terms, and the Tong Shu almanac with auspicious-day search. Every point where the classical schools disagree is a typed request parameter with a named default, and the choice comes back in a conventions object on the response, so a chart you generate today can be reproduced exactly. Whether you need a BaZi calculator, a Chinese zodiac page, a lunar calendar converter or an almanac date picker, it is one key and one domain.
What you can build
- BaZi chart readers (four pillars, Day Master, Ten Gods, hidden stems, Na Yin, five-element balance)
- Day Master strength calculators (strong or weak, with the three factors that decide it)
- Luck pillar timelines (the ten-year cycles, plus annual pillars for a year-by-year view)
- Chinese zodiac pages and quizzes ("what is my Chinese zodiac sign", compatibility, per-animal profiles)
- Annual forecast and Lunar New Year re-engagement features (including the ben ming nian flag)
- Lunar calendar apps (Gregorian to lunar and back, leap months, lunar birthday reminders)
- Solar term calendars (all 24 terms with the exact instant each one begins)
- Tong Shu almanac day views (day officer, lunar mansion, clash animal, what the day favours)
- Date pickers that search a range for auspicious wedding, moving, or business-opening days
Prerequisites
- A RoxyAPI key from /account.
- Birth
date(YYYY-MM-DD),time(HH:MM:SS), andtimezone(IANA name preferred, e.g."America/New_York"). Latitude and longitude are optional; onlylongitudematters, and only if you switchhourClocktolocal-meanorsolar, which return 400 without it. - For city to lat/lng/timezone use
GET /location/search. Required if your users type a city name. - The zodiac and calendar endpoints need less:
POST /chinese-astrology/zodiac/signtakes a date only, and the almanac endpoints take a date in the path.
Install
npm install @roxyapi/sdk
pip install roxy-sdk
composer require roxyapi/sdk
dotnet add package RoxyApi.Sdk
go get github.com/RoxyAPI/sdk-go
Call the endpoint
The #1 Chinese astrology call is the BaZi chart. One POST returns all four pillars with their stems, branches, Ten Gods, hidden stems and Na Yin, plus the Day Master, the five-element count, and every interaction between the pillars. Verified operationId: generateBaziChart.
# 1. geocode the city (only needed if you plan to use a solar hour clock)
curl "https://roxyapi.com/api/v2/location/search?q=New+York" \
-H "X-API-Key: $ROXY_API_KEY"
# 2. post the BaZi request
curl -X POST https://roxyapi.com/api/v2/chinese-astrology/bazi/chart \
-H "X-API-Key: $ROXY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"date": "1990-07-15",
"time": "14:30:00",
"timezone": "America/New_York"
}'
import { createRoxy } from '@roxyapi/sdk';
const roxy = createRoxy(process.env.ROXY_API_KEY!);
const { data: bazi } = await roxy.chineseAstrology.generateBaziChart({
body: { date: '1990-07-15', time: '14:30:00', timezone: 'America/New_York' },
});
console.log(bazi.pillars.length); // 4 (year, month, day, hour)
console.log(bazi.pillars[2].id); // "xin-si" <- the day pillar
console.log(bazi.dayMaster.chinese); // "辛"
console.log(bazi.dayMaster.element); // "Metal"
console.log(bazi.dayMaster.polarity); // "yin"
console.log(bazi.zodiacAnimal); // "horse"
console.log(bazi.fiveElements[0]); // { element: "Wood", count: 1, level: "balanced", reading: "..." }
console.log(bazi.interactions[0].type); // "six-combination"
console.log(bazi.conventions); // { dayBoundary: "split-zi", yearBoundary: "li-chun", hourClock: "clock" }
import os
from roxy_sdk import create_roxy
roxy = create_roxy(os.environ['ROXY_API_KEY'])
bazi = roxy.chinese_astrology.generate_bazi_chart(
date='1990-07-15', time='14:30:00', timezone='America/New_York',
)
print(bazi['dayMaster']['element'], bazi['dayMaster']['polarity'])
print([p['id'] for p in bazi['pillars']])
<?php
use function RoxyAPI\Sdk\createRoxy;
$roxy = createRoxy(getenv('ROXY_API_KEY'));
$bazi = $roxy->chineseAstrology->generateBaziChart(
date: '1990-07-15',
time: '14:30:00',
timezone: 'America/New_York',
);
echo $bazi['dayMaster']['element'], ' ', $bazi['dayMaster']['polarity'];
using RoxyApi;
using Microsoft.Kiota.Abstractions; // for the Date and Time types
var roxy = new RoxyClient(Environment.GetEnvironmentVariable("ROXY_API_KEY")!);
var bazi = await roxy.ChineseAstrology.Bazi.Chart.PostAsync(new()
{
Date = new Date(1990, 7, 15),
Time = new Time(14, 30, 0),
Timezone = new() { String = "America/New_York" },
});
Console.WriteLine(bazi!.DayMaster!.Element); // "Metal"
Console.WriteLine(bazi.DayMaster.Polarity); // "yin"
Console.WriteLine(bazi.Pillars!.Count); // 4
Console.WriteLine(bazi.ZodiacAnimal); // "horse"
import (
"context"
"time"
roxyapi "github.com/RoxyAPI/sdk-go"
)
roxy, _ := roxyapi.NewRoxy("YOUR_API_KEY")
var tz roxyapi.GenerateBaziChartJSONBody_Timezone
_ = tz.FromGenerateBaziChartJSONBodyTimezone1("America/New_York")
bazi, _ := roxy.ChineseAstrology.GenerateBaziChart(context.Background(), nil,
roxyapi.GenerateBaziChartJSONRequestBody{
Date: roxyapi.Date(1990, time.July, 15), Time: "14:30:00", Timezone: tz,
})
claude mcp add-json --scope user roxy-chinese-astrology '{"type":"http","url":"https://roxyapi.com/mcp/chinese-astrology","headers":{"X-API-Key":"YOUR_KEY"}}'
Then in any MCP client: "what is the BaZi chart for someone born July 15 1990 at 2:30 PM in New York, and is the Day Master strong or weak?" The agent calls the BaZi chart tool, then the Day Master strength tool, and explains both. Full setup for Cursor, Claude Desktop, Antigravity, and other clients: MCP guide.
Read the response
The BaZi response has six parts. Read them in this order and you have a complete chart.
| Field | What it is | What to do with it |
|---|---|---|
pillars | Four objects, position of year, month, day, hour. Each has stem, branch, tenGod, hiddenStems, naYin | The chart grid. Render stem.chinese over branch.chinese in four columns |
dayMaster | The day pillar stem: chinese, pinyin, element, polarity, nature | The headline of any reading. Everything else is read relative to it |
fiveElements | Five objects, one per phase, each with count and level | The balance bar chart, and the fastest visual a user understands |
interactions | Combinations and clashes between pillars, each with type, quality, positions, meaning | The dynamics section. quality is harmonious or challenging, safe to branch on |
conventions | The three school settings this chart was built with | Show it, or store it. It is what makes the chart reproducible |
summary | One paragraph of composed prose | Use it, or ignore it and write your own from the fields above |
The day pillar is pillars[2], and its tenGod.name is always "Day Master", because a stem has no Ten God relationship to itself.
The three conventions (read this before you compare charts)
This is the part that decides whether your chart agrees with a chart from anywhere else. Chinese astrology has three long-standing disagreements about where a boundary falls, and each one is a request parameter here rather than a hidden assumption.
| Parameter | Default | Other values | What it moves |
|---|---|---|---|
dayBoundary | split-zi | midnight, early-zi | The day pillar (and so the Day Master) and the hour pillar, for births in the 11 PM to midnight hour |
yearBoundary | li-chun | lunar-new-year | The year pillar and zodiac animal for births in late January and early February |
hourClock | clock | local-mean, solar | The hour pillar, by correcting civil clock time toward true local time |
yearBoundary is the one your users will notice. Take 14 February 2026:
# folk convention: the year turns at Lunar New Year
curl -X POST https://roxyapi.com/api/v2/chinese-astrology/zodiac/sign \
-H "X-API-Key: $ROXY_API_KEY" -H "Content-Type: application/json" \
-d '{"date":"2026-02-14"}'
# => animal Snake, element Wood, yearPillar "yi-si"
# BaZi convention: the year turns at Li Chun, the solar term
curl -X POST https://roxyapi.com/api/v2/chinese-astrology/zodiac/sign \
-H "X-API-Key: $ROXY_API_KEY" -H "Content-Type: application/json" \
-d '{"date":"2026-02-14","yearBoundary":"li-chun"}'
# => animal Horse, element Fire, yearPillar "bing-wu"
Same date, two correct answers: a Wood Snake year under lunar-new-year, a Fire Horse year under li-chun. Neither is a bug and neither is the right answer in general, which is why the response always tells you which one it used.
Pick a convention once, store it with the chart
Choose your defaults at product level, then persist the conventions object alongside every saved chart. When a user asks why your app disagrees with a chart their teacher drew, you can answer in one line instead of recomputing.
Note the two defaults that differ on purpose: POST /chinese-astrology/zodiac/sign defaults yearBoundary to lunar-new-year, because that is what someone asking for their zodiac animal expects. Everything in the BaZi family defaults to li-chun, because that is what the Four Pillars method uses. Both echo the choice back.
dayBoundary matters far less often, but when it bites it moves the Day Master itself, which is the value a whole reading hangs on. A birth at 23:30 on 15 June 1990 in Shanghai separates all three:
dayBoundary | Day pillar | Hour pillar | Day Master |
|---|---|---|---|
split-zi (default) | xin-hai | geng-zi | 辛 Metal |
midnight | xin-hai | wu-zi | 辛 Metal |
early-zi | ren-zi | geng-zi | 壬 Water |
midnight moves the hour pillar, early-zi moves the day pillar and the Day Master with it. Outside the 11 PM to midnight hour all three agree, so this only affects a thin slice of your users, and for them it changes the headline.
Render the result
The four-pillar grid is the standard presentation, and the response maps onto it directly. 15 lines of markup is enough:
<table class="bazi">
<thead><tr><th>Hour</th><th>Day</th><th>Month</th><th>Year</th></tr></thead>
<tbody>
<tr class="stems"> <!-- reverse the array: a BaZi chart reads hour to year, left to right -->
<td>${p[3].stem.chinese}</td><td>${p[2].stem.chinese}</td>
<td>${p[1].stem.chinese}</td><td>${p[0].stem.chinese}</td>
</tr>
<tr class="branches">
<td>${p[3].branch.chinese}</td><td>${p[2].branch.chinese}</td>
<td>${p[1].branch.chinese}</td><td>${p[0].branch.chinese}</td>
</tr>
<tr class="ten-gods">
<td>${p[3].tenGod.name}</td><td>Day Master</td>
<td>${p[1].tenGod.name}</td><td>${p[0].tenGod.name}</td>
</tr>
</tbody>
</table>
Colour each cell by stem.element and branch.element (Wood, Fire, Earth, Metal, Water) and you have the standard presentation. Those element strings are canonical English in every language, so they are safe as CSS class names. For ready-made chart rendering, see the component catalog in @roxyapi/ui.
Ship the rest
Day Master strength, the verdict a reading is built on
POST /chinese-astrology/bazi/day-master (calculateDayMasterStrength) returns verdict (strong or weak), a numeric score, and the three factors that produced it: month command, rooting, and party support, each with its own contribution. It also returns favorableElements and unfavorableElements, which is what every downstream recommendation reads.
curl -X POST https://roxyapi.com/api/v2/chinese-astrology/bazi/day-master \
-H "X-API-Key: $ROXY_API_KEY" -H "Content-Type: application/json" \
-d '{"date":"1990-07-15","time":"14:30:00","timezone":"America/New_York"}'
Because the factors are published separately and sum into score, you can show a user why the verdict came out the way it did, or apply your own weighting instead of ours.
Luck pillars, the ten-year timeline
POST /chinese-astrology/bazi/luck-pillars (calculateLuckPillars) returns the decade cycles with startAge, startYear, endYear and the Ten God of each. It requires gender in the body, because the direction the pillars run (forward or reverse) depends on it and cannot be derived from the chart alone. Optional count sets how many pillars to return; annualFromYear and annualYears add the year-by-year pillars on top.
Annual forecast, the Lunar New Year hook
POST /chinese-astrology/bazi/annual-forecast (calculateAnnualForecast) takes the birth body plus a year and returns that year pillar against the natal chart: tenGod, branchTenGod, yearBranchRelation, and benMingNian. benMingNian is true when the year returns the birth animal, which happens once every twelve years and is the single best re-engagement trigger in the domain.
BaZi compatibility, for matchmaking
POST /chinese-astrology/bazi/compatibility (calculateBaziCompatibility) takes personA and personB (each a birth object) and returns dayMasterRelation, the interactions between the two charts, a score, and harmoniousCount and challengingCount.
The zodiac family, for content and quizzes
POST /chinese-astrology/zodiac/sign(calculateZodiacAnimal) takes a date only and answers the most searched question in the domain. Returns theanimal, theyearPillar, the year stemelement, andpolarity.GET /chinese-astrology/zodiac/compatibility/{sign1}/{sign2}(getZodiacCompatibility) is one call per pair with no birth time. Returnsrelationship(a stable id such assecret-friend), ascoreout of 100, averdict, plusstrengths,frictionsandadvicearrays. Any two of the twelve animals work, in either order, and a sign paired with itself returns thesamerelationship.GET /chinese-astrology/zodiac/{id}/daily(getDailyZodiacReading) is the daily-content surface:energyRating,overview,love,career,advice, derived from the day pillar. Deterministic per animal and date, so it caches cleanly and every user of a sign sees the same reading.GET /chinese-astrology/zodiac/animals(listZodiacAnimals) andGET /chinese-astrology/zodiac/animals/{id}(getZodiacAnimal) are the catalog. The single-animal call carriestrine,secretFriend,clashPartner,harmPartner,elementVariantsandcompatibilitySummary, which is enough to fill a per-animal page.
The calendar family
POST /chinese-astrology/calendar/lunar-date(calculateLunarDate) converts in both directions. Senddatefor Gregorian to lunar, orlunarYearpluslunarMonthpluslunarDay(andisLeapMonth) for the reverse. This is what a lunar birthday reminder is built on.GET /chinese-astrology/calendar/solar-terms/{year}(listSolarTerms) returns all 24 terms for a solar year, each withinstantUtc,localDateandlocalTime. A solar term is an instant, not a day, and this is the call that settles a month-pillar boundary dispute.GET /chinese-astrology/calendar/day/{date}(getAlmanacDay) is the Tong Shu day view:dayOfficer,mansion,clashAnimal, plusfavoursandavoidsarrays of activity ids.GET /chinese-astrology/calendar/monthly(getMonthlyAlmanac) is the same data as a month grid, one call instead of thirty.POST /chinese-astrology/calendar/auspicious-days(lookupAuspiciousDays) searches a date range for a namedactivityand returns the matching days in full. This is date selection, the thing people actually book a practitioner for.
curl -X POST https://roxyapi.com/api/v2/chinese-astrology/calendar/auspicious-days \
-H "X-API-Key: $ROXY_API_KEY" -H "Content-Type: application/json" \
-d '{
"activity": "wedding",
"startDate": "2026-09-01",
"endDate": "2026-10-31",
"avoidAnimal": "rat"
}'
activity is one of wedding, travel, moving-house, opening-business, signing-contracts, construction, groundbreaking, burial, medical-treatment, praying. Optional avoidAnimal drops any day that clashes with a given animal, which is how you exclude the couple own signs from a wedding search.
The five elements catalog
GET /chinese-astrology/elements (listFiveElements) returns the wu xing with generatingCycle and controllingCycle as ordered arrays. One home for the five phases, shared with feng shui rather than duplicated.
See the full domain at the API Reference.
Reply in the user language
Every endpoint in this domain accepts ?lang=, and this is the one catalog domain that ships both Chinese scripts: zh-Hant (Traditional) and zh-Hans (Simplified), alongside English, Turkish, German, Spanish, Hindi, Portuguese, French and Russian. 10+ languages in total, on the same key.
curl -X POST "https://roxyapi.com/api/v2/chinese-astrology/bazi/chart?lang=zh-Hant" \
-H "X-API-Key: $ROXY_API_KEY" -H "Content-Type: application/json" \
-d '{"date":"1990-07-15","time":"14:30:00","timezone":"America/New_York"}'
Identifiers never translate, and that is deliberate. zodiacAnimal stays "horse", dayMaster.element stays "Metal", interactions[].quality stays "harmonious", in every language. Display text arrives in a sibling field named *Localized, which is present only when you pass lang:
const label = bazi.zodiacAnimalLocalized ?? bazi.zodiacAnimal; // "馬" with lang=zh-Hant, else "horse"
if (bazi.zodiacAnimal === 'horse') { /* always safe, in every language */ }
Switch your code on the canonical field, render the localized one. Do it the other way round and your app breaks the first time a user changes language.
Gotchas
- The BaZi chart needs a real birth time. The hour pillar is one of the four, so a guessed time gives a chart that is three-quarters right and looks completely right. If you do not have the time, use
POST /chinese-astrology/zodiac/sign(date only) and say so in your UI rather than defaulting the time to noon. timezonecomes back as a number. You send"America/New_York", andbirthData.timezoneechoes the resolved offset (-4for a July 1990 birth, DST applied). Send the IANA name, never a fixed offset, and the server does the DST resolution against the birth date.- The chart reads right to left.
pillars[0]is the year andpillars[3]is the hour, but the conventional presentation puts the hour on the left. Reverse the array when you render, not when you read. - Two different fields are called an element. On
zodiac/sign, top-levelelementis the year stem phase (Metal), whileanimal.elementis the fixed phase of the branch (Firefor the Horse). They disagree for most years, and both are correct. genderon luck pillars selects a formula, not an identity. It sets the direction the pillars run. Same for the feng shui Kua number. Label the input in your UI in whatever way suits your users, and passmaleorfemaleto the API.- Auspicious-day search is capped at 93 days. A wider range returns 400 with the day count in the message. Page the search yourself for a longer window.
- Lunar dates are the same everywhere on earth. The lunisolar calendar family is computed on a single reference frame (
referenceOffset: 8), which is what the national standard specifies. A lunar date does not shift with the caller timezone, so do not pass one expecting it to. animalLocalizedand friends are absent, not null, in English. Use??and read the canonical field as the fallback.- Every call bills at a flat 1 request. REST and Remote MCP are identical. There are no per-domain fees and no batch endpoints.
Frequently asked questions
What is a BaZi API and what does it return?
A BaZi API converts a birth date, time and timezone into the Four Pillars of Destiny: the year, month, day and hour pillars, each a Heavenly Stem over an Earthly Branch. POST /chinese-astrology/bazi/chart returns all four with their Ten Gods, hidden stems and Na Yin, plus the Day Master, the five-element count, and every combination and clash between the pillars.
Why does my Chinese zodiac animal differ between two calculators?
Because they disagree about when the year starts. The folk convention turns the year at Lunar New Year, the Four Pillars convention turns it at Li Chun, the solar term in early February, and the two can be weeks apart. RoxyAPI makes that a request parameter, yearBoundary, and echoes the choice back on every response, so a chart can always be reproduced.
Do I need the exact birth time for a BaZi chart?
For the full chart, yes. The hour pillar is one of the four, and the Day Master can move for births near a day boundary. If you only have the date, call POST /chinese-astrology/zodiac/sign, which returns the animal, the year pillar and the year element from a date alone.
Can I search for an auspicious wedding or moving date?
Yes. POST /chinese-astrology/calendar/auspicious-days takes an activity, a start date and an end date, and returns every matching day with its pillars, day officer, lunar mansion and clash animal. Ranges are capped at 93 days per call, and an optional avoidAnimal filters out days that clash with a given sign.
Does the API support Chinese language output?
Yes, in both scripts. Pass ?lang=zh-Hant for Traditional or ?lang=zh-Hans for Simplified, alongside eight other languages on the same key. Machine-readable identifiers stay canonical English in every language, and translated display text arrives in a matching *Localized field.
How is this different from Western astrology?
They are separate systems with separate inputs. Western astrology reads planetary positions against the zodiac; BaZi reads a sexagenary calendar of stems and branches and the interaction of five elements. Both are full domains here on one key, so a single profile can carry a natal chart and a BaZi chart side by side.
Ready-made starter
There is no Chinese-astrology-only template yet. The flagship astrology-ai-chatbot template connects this domain by default over Remote MCP, so cloning it gives you a working BaZi and zodiac chatbot with no wiring; browse the catalog at /starters. For a custom build, the Next.js integration guide is the fastest path.
What to build next
- The feng shui guide covers the other half of Chinese metaphysics: Kua numbers, Eight Mansions, flying stars, and the annual afflictions. The two share the same year boundary and the same five elements.
- The complete birth profile tutorial assembles a BaZi chart alongside the natal chart, kundli, bodygraph and numerology into one cached payload for an AI agent.
- The AI chatbot tutorial shows tool registration so users can ask "is my Day Master strong" in natural language.
- The caching guide explains which of these calls are safe to cache forever. The BaZi chart is; the daily zodiac reading is not.