Calculate endpoint — Four Pillars & the five-element distribution.

The base endpoint of the Korean Saju (사주 / Four Pillars, the Korean reading of Bazi) engine. Post a birthdate and get the Four Pillars (year, month, day, hour), the distribution of the five elements (wood, fire, earth, metal, water), the Day Master, and the zodiac animal — pure structured data, no interpretation layer. One POST, clean JSON, 10 languages.

What it returns

Where /interpret adds an analysis layer (Ten Gods, Yongshin, Daeun), /calculate stays at the foundation: it converts a birthdate into the eight characters of a Saju chart and counts how the five elements are distributed across them. That makes it the right call when you only need the raw chart and the elemental balance — for example to drive a color theme, a personality summary, or your own downstream scoring.

Request

POST /api/v1/calculate takes a solar birthdate as year, month, day, hour, gender, plus an optional lang. Use hour: -1 when the birth time is unknown — the Hour Pillar comes back null and the element counts are computed from the remaining three pillars.

curl -X POST https://saju-api.pages.dev/api/v1/calculate \
  -H "X-API-Key: sajuapi_free_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "year":  1990,
    "month": 5,
    "day":   15,
    "hour":  14,
    "gender":"M",
    "lang":  "en"
  }'
const res = await fetch("https://saju-api.pages.dev/api/v1/calculate", {
  method: "POST",
  headers: {
    "X-API-Key": "sajuapi_free_YOUR_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    year: 1990, month: 5, day: 15, hour: 14, gender: "M", lang: "en",
  }),
});
const data = await res.json();
console.log(data.pillars);     // Four Pillars
console.log(data.elements);    // { wood, fire, earth, metal, water }
console.log(data.day_master);  // stem, element, polarity
import requests

res = requests.post(
    "https://saju-api.pages.dev/api/v1/calculate",
    headers={"X-API-Key": "sajuapi_free_YOUR_KEY"},
    json={"year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "M", "lang": "en"},
)
data = res.json()
print(data["pillars"])     # Four Pillars
print(data["elements"])    # {"wood":..,"fire":..,"earth":..,"metal":..,"water":..}
print(data["day_master"])  # stem, element, polarity

Request fields

FieldTypeNotes
yearintegerRequired. Solar (Gregorian) year, 1920–2050.
monthintegerRequired. 1–12.
dayintegerRequired. 1–31.
hourintegerRequired. 0–23, or -1 if the birth time is unknown.
genderstringRequired. M or F.
langstringOptional. One of ko, en, ja, zh, es, pt-br, vi, id, hi, th.

Response fields

FieldWhat it is
inputThe normalized birthdate the engine used for this calculation.
pillarsThe Four Pillars (year / month / day / hour), each with stem, branch, and their Hanja. hour is null when the birth time is unknown.
elementsThe five-element distribution: integer counts for wood, fire, earth, metal, and water across the chart.
day_masterThe Day Master — the Day Pillar stem, with its element and polarity (yin / yang).
zodiacThe zodiac animal for the chart, derived from the Year Pillar branch.
tierYour API tier (e.g. free).
remainingRequests left in your daily quota.

Response shape

{
  "input": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "M", "lang": "en" },
  "pillars": {
    "year":  { "stem": "...", "branch": "...", "stem_hanja": "...", "branch_hanja": "..." },
    "month": { "stem": "...", "branch": "...", "stem_hanja": "...", "branch_hanja": "..." },
    "day":   { "stem": "...", "branch": "...", "stem_hanja": "...", "branch_hanja": "..." },
    "hour":  { "stem": "...", "branch": "...", "stem_hanja": "...", "branch_hanja": "..." }
  },
  "elements": { "wood": 0, "fire": 2, "earth": 2, "metal": 3, "water": 1 },
  "day_master": { "stem": "...", "element": "metal", "polarity": "yang" },
  "zodiac": "horse",
  "tier": "free",
  "remaining": 98
}
Field presence is stable. Treat blocks defensively (check for a key before reading nested values) and remember that pillars.hour is null when the birth time is unknown.

Reading the element distribution

The elements object always sums to the number of pillars counted (eight characters for a full chart, six when the birth time is unknown). A count of 0 for an element means that element is absent from the chart — a common signal in Saju for an imbalance. Because the values are plain integers, you can drive your own UI from them directly:

const e = data.elements;                       // { wood, fire, earth, metal, water }
const total = e.wood + e.fire + e.earth + e.metal + e.water;
const dominant = Object.keys(e).reduce((a, b) => (e[b] > e[a] ? b : a));
const missing  = Object.keys(e).filter((k) => e[k] === 0);

// e.g. theme the chart by its dominant element, or flag missing ones
console.log(dominant);  // "metal"
console.log(missing);   // ["wood"]

Common use cases

Errors

StatusMeaning
400invalid_input with a reason (e.g. year_out_of_range, gender_must_be_M_or_F, unsupported_lang). Year range is 1920–2050.
401Missing or malformed X-API-Key.
405Use POST for this endpoint.
429Daily quota for your tier exceeded.

Related

Saju (사주 / Four Pillars of Destiny) is a traditional cultural and fortune-telling system. The chart and element distribution returned by this API are for entertainment and reflection only and are not predictions, guarantees, or financial, medical, legal, or professional advice.