# Chinese zodiac and calendar

The year animal is the best known part of the tradition and the most often computed wrong. The BaZi year does not begin on 1 January, and it does not begin at Chinese New Year. It begins at **立春 Lichun**, the instant the Sun's apparent longitude reaches 315°. In 2026 that is `2026-02-03T20:02:08Z`, which is 4 February at 04:02 Beijing time. Somebody born on 2 February belongs to the previous animal, whatever the calendar on the wall says.

## Endpoints

| Endpoint | Credits | What it returns |
|---|---:|---|
| `POST /v1/chinese/zodiac/animal` | 10 | Year animal, pillar, branch and stem elements |
| `POST /v1/chinese/zodiac/element` | 10 | The branch's fixed element and the stem's cycling one |
| `POST /v1/chinese/zodiac/inner-animal` | 10 | Inner animal: the month branch |
| `POST /v1/chinese/zodiac/secret-animal` | 10 | Secret animal: the hour branch |
| `POST /v1/chinese/zodiac/compatibility` | 10 | Compatibility of two animals by 三合 and 六冲 |
| `POST /v1/chinese/lunar-date` | 10 | Lunar date, leap month, Chinese New Year |
| `POST /v1/chinese/solar-terms` | 10 | All 24 terms of a year, to the second |

## Three animals, not one

Magazine horoscopes know one animal. The tradition knows three, and they answer different questions.

| Animal | From | What it carries |
|---|---|---|
| Outer | year branch | How other people see the person |
| Inner | month branch | Motivation, the private self |
| Secret | hour branch | The deepest layer, often hidden from the person too |

The inner animal is bounded by the exact 節 instants rather than by mid-month, so a birth on 5 May and one on 6 May can land on different animals.

```bash
curl -X POST https://api.astroway.info/v1/chinese/zodiac/inner-animal \
  -H "X-Api-Key: $ASTROWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"date":"1990-05-15","time":"14:30:00","timezoneOffset":3}'
```

```json
{
  "ok": true,
  "data": {
    "innerAnimal": "Snake",
    "glyph": "🐍",
    "description": "Inner animal = the BaZi month branch, bounded by the exact 節 instants. Represents internal motivations and the private self."
  }
}
```

## Two elements for one year

Somebody born in 1990 is a "metal horse", and that name holds two different elements which are easy to conflate.

- The **cycling** element comes from the heavenly stem and turns over every two years: 庚 is metal.
- The **fixed** element belongs to the earthly branch permanently: 午 is fire, and a horse is always a fire horse.

`/chinese/zodiac/element` returns both as separate fields, `fixedElement` and `cyclingElement`, instead of picking one for you.

## Compatibility

The score is built on 三合 (three harmonies) and 六冲 (six clashes), which is the geometry of the branch circle rather than a list of opinions.

```bash
curl -X POST https://api.astroway.info/v1/chinese/zodiac/compatibility \
  -H "X-Api-Key: $ASTROWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"person1":{"date":"1990-05-15"},"person2":{"date":"1988-02-20"}}'
```

```json
{
  "person1": { "solarYear": 1990, "animal": "Horse" },
  "person2": { "solarYear": 1988, "animal": "Dragon" },
  "compatibility": {
    "score": 65,
    "category": "good",
    "notes": ["Compatible enough; complementary differences."]
  }
}
```

<Aside type="note" title="Animal compatibility is one layer, not a chart">
Comparing year animals is the coarsest cut available: it knows exactly one character out of eight about a person. For a real reading take `/v1/bazi/chart` for both and look at the interactions across all four pillars.
</Aside>

## The lunar date

```bash
curl -X POST https://api.astroway.info/v1/chinese/lunar-date \
  -H "X-Api-Key: $ASTROWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"date":"2026-02-17"}'
```

```json
{
  "gregorianDate": "2026-02-17",
  "lunar": { "month": 1, "isLeapMonth": false, "day": 1, "monthStart": "2026-02-17", "label": "month 1, day 1" },
  "chineseNewYear": "2026-02-17"
}
```

A month begins with the Beijing day that contains a new moon. A leap month repeats the number of the month it follows and carries no 中氣: that is the reason it exists, not a side effect.

<Aside type="caution" title="Before 1929">
Before 1929 the calendar is reckoned in Beijing local mean time (UTC+7:45:40), which is the historical basis rather than a convention of ours. A lunation falling within minutes of local midnight can still place a month one day away from the printed almanac of the period, since those were computed to the accuracy of their day.
</Aside>

## The twenty-four solar terms

A term is not a date from a table. It is the instant the Sun's apparent longitude becomes a multiple of 15°. We take it from the ephemeris, so the answer is the same for any year inside the domain and does not depend on whether somebody refreshed a table.

```bash
curl -X POST https://api.astroway.info/v1/chinese/solar-terms \
  -H "X-Api-Key: $ASTROWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"year":2026}'
```

The `terms` array carries all twenty-four; the first is shown here:

```json
{
  "year": 2026,
  "terms": [
    {
      "index": 0,
      "chinese": "立春",
      "pinyin": "Lichun",
      "english": "Start of Spring",
      "sunLongitude": 315,
      "utc": "2026-02-03T20:02:08Z",
      "beijing": "2026-02-04T04:02:08+08:00",
      "opensPillarMonth": true
    }
  ]
}
```

Twelve of the twenty-four carry `opensPillarMonth: true`: those are the 節 that open a pillar month. The other twelve are 中氣, which halve the month and decide which month a leap month follows.

<Aside type="note" title="A term is an instant, and its calendar day is not the same everywhere">
Read `utc` rather than `beijing` if your reader is not in China. China and Hong Kong reckon the instants in UTC+8, Japan and Korea in UTC+9, Vietnam in UTC+7, so one hour in twenty-four is a window where the national almanacs print different calendar days. That works out at about one term a year. In 2026 it is two: 雨水 falls on 18 February in Beijing and 19 February in Tokyo, 芒種 on 5 and 6 June. Our instants reproduce both publications to the minute.
</Aside>

## Languages

Animals and elements are translated into 21 languages. Add `?lang=` or `"language"` in the body and a `*Name` field appears next to the English token:

```bash
curl -X POST "https://api.astroway.info/v1/chinese/zodiac/animal?lang=es" \
  -H "X-Api-Key: $ASTROWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"date":"1990-05-15"}'
```

```json
{ "animal": "Horse", "animalName": "Caballo", "element": { "fixed": "Fire", "fixedName": "Fuego" } }
```

The English fields stay where they are forever: localisation adds, it does not replace.
