占星星盤運算 API — 本命盤、合盤、行運、推運、太陽回歸、組合盤
Base URL 為 同源(same-origin):所有路徑皆為相對路徑(例如 /api/v1/charts),直接對本站發送請求即可。
本 API 目前為 Beta、開放測試(open beta)狀態:
API_KEY_MODE=open)required 模式,屆時匿名呼叫將回 401 key_required。金鑰的取得、傳遞方式與用量端點詳見驗證與用量。
所有請求與回應皆為 JSON(Content-Type: application/json)。所有 /api 回應皆帶有 Access-Control-Allow-Origin: *,可直接從瀏覽器跨域呼叫;OPTIONS /api/v1/* 預檢請求回傳 204,並帶 Access-Control-Allow-Methods: POST,GET,OPTIONS 與 Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key。
機器可讀的完整規格見 /openapi.json(OpenAPI 3.1)。
以下所有需要出生資料的端點(/charts 本身、/synastry 的 a/b、/transits・/progressions・/solar-return 的 natal、/composite 的 a/b)都使用同一組欄位與驗證規則:
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
birth_date | string | 是 | 出生日期,格式 YYYY-MM-DD(需補零),並須為有效日期 | "1990-01-01" |
birth_time | string | 是 | 出生時間(當地時間),格式 H:MM 或 HH:MM,24 小時制(時 0–23、分 0–59) | "12:00" |
latitude | number | 是 | 出生地緯度,範圍 −90 ~ 90(須為 JSON 數字,字串會被拒絕) | 25.033 |
longitude | number | 是 | 出生地經度,範圍 −180 ~ 180(東經為正) | 121.5654 |
timezone | string | 是 | IANA 時區識別碼 | "Asia/Taipei" |
house_system | string | 否 | 宮位制。"P" / "placidus" = Placidus(預設);"W" / "whole_sign" = 整宮制。不分大小寫;其他值回 400 invalid_house_system | "W" |
API 回應預設使用繁體中文(zh-TW)詞彙。所有起盤端點(/charts、/synastry、/transits、/progressions、/composite、/solar-return)接受選填的請求主體欄位 lang;GET /api/v1/cities 接受查詢參數 ?lang=。/api/v1/health 無語言參數。
| 送入值(不分大小寫) | 語言 | 說明 |
|---|---|---|
zh-TW、zh-tw、zh_tw、zh | 繁體中文 | 預設:省略或 null 時等同 zh-TW,回應與不帶 lang 完全相同 |
en | English | 行星/星座/相位等詞彙譯為英文 |
ja | 日本語 | 詞彙譯為日文(部分詞彙與中文同形) |
ko | 한국어 | 詞彙譯為韓文 |
其他任何值(含空字串 "")回 400 invalid_lang,且此錯誤訊息固定為 zh-TW。
lang 只翻譯「詞彙值」,不改變任何 JSON 結構:
planet、a_planet、b_planet、transit_planet、natal_planet、progressed_planet、planet_a、planet_b、apex、ruling_planet、zodiac、aspect_type、pattern_type、element 欄位的值,以及 patterns[].planets 陣列中的星體名稱a_planets_in_b_houses/b_planets_in_a_houses 的行星名稱鍵,與 element_stats.elements/element_stats.modalities 的元素/模式鍵(宮號、計數等「值」不變)error.message 依請求的 lang 在地化/cities 帶 lang=en/ja/ko 時,name 與 country 改為英文名(不提供日文/韓文城市名)planet、zodiac 等 key 名稱)、input 回聲區塊(原樣回傳)、所有數字、house_system 的 "P"/"W"、錯誤 code 值(語言無關 — 程式邏輯請一律以 code 判斷)invalid_json)時伺服器讀不到 lang,該錯誤訊息固定為 zh-TW。
地(火/地/風/水),模式為 活動/不動/柔軟;韓文(ko)元素為 불/흙/공기/물,模式為 활동궁/고정궁/변통궁。
請求範例
{
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei",
"lang": "ja"
}
回應 200(實際輸出,節錄)
{
"data": {
"input": { /* 原樣回傳,不翻譯 */ },
"chart": {
"ascendant": { "zodiac": "牡羊座", "degree": 16.4422, "total_degree": 16.4422 },
"house_system": "P",
"planets": [
{ "planet": "太陽", "zodiac": "山羊座", "house": 9, "degree": 10.4744, "total_degree": 280.4744, "retrograde": false,
"aspects": [
{ "planet": "木星", "aspect_type": "オポジション", "orb": 5.28 },
{ "planet": "土星", "aspect_type": "コンジャンクション", "orb": 5.14 }
// …其餘 2 筆省略
] },
{ "planet": "月", "zodiac": "水瓶座", "house": 11, "degree": 28.7886, "total_degree": 328.7886, "retrograde": false },
{ "planet": "ドラゴンヘッド", "zodiac": "水瓶座", "house": 11, "degree": 16.863, "total_degree": 316.863, "retrograde": false }
// …其餘 14 筆省略(結構不變,共 17 筆)
],
"element_stats": {
"elements": { "火": 1, "地": 5, "風": 2, "水": 2 },
"modalities": { "活動": 6, "不動": 3, "柔軟": 1 }
}
// …houses/patterns 結構不變
}
}
}
API 金鑰讓你把呼叫用量歸戶、設定每月用量上限,並查詢自己的用量。是否強制帶金鑰由伺服器環境變數 API_KEY_MODE 控制:
API_KEY_MODE | 行為 |
|---|---|
open(預設,本站目前狀態) | 金鑰選填。不帶金鑰=匿名呼叫,一切正常;帶了金鑰則把該次用量計入該金鑰。 |
required | 金鑰必填。所有計費端點的匿名呼叫回 401 key_required。 |
open 模式:你現在完全不帶金鑰也能呼叫本站所有端點(唯一例外是 GET /api/v1/usage,因為匿名用量無從歸戶,即使在 open 模式也需要金鑰)。以下關於金鑰的說明是為了讓你在需要時(或伺服器日後切換為 required)能無痛接上。
金鑰長相為 ak_XXXXXXXX…。以下任一種方式擇一即可(優先序:Authorization > X-API-Key > ?api_key=):
| 方式 | 範例 |
|---|---|
請求標頭 Authorization: Bearer | Authorization: Bearer ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ |
請求標頭 X-API-Key | X-API-Key: ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ |
查詢參數 ?api_key= | /api/v1/cities?q=tai&api_key=ak_7hgEJAyQ… |
OPTIONS /api/v1/*)已允許 Content-Type, Authorization, X-API-Key 標頭,可直接從瀏覽器帶金鑰跨域呼叫。
下列端點在 open 模式允許匿名,成功(HTTP 200)時計入用量一次;在 required 模式則必須帶金鑰:
POST /api/v1/charts、/synastry、/transits、/progressions、/composite、/solar-returnGET /api/v1/cities不計入用量:GET /api/v1/health(永遠公開、免金鑰)與 GET /api/v1/usage(需金鑰,但查詢自身用量本身不計費)。
| HTTP | code | 觸發條件 | 回應範例 |
|---|---|---|---|
| 401 | key_required | required 模式下匿名呼叫計費端點;或任何模式下呼叫 /usage 卻未帶金鑰 | {"error":{"code":"key_required","message":"此端點需要 API 金鑰"}} |
| 401 | invalid_api_key | 金鑰不存在或已被撤銷(revoked) | {"error":{"code":"invalid_api_key","message":"API 金鑰無效或已撤銷"}} |
| 429 | quota_exceeded | 該金鑰本月用量已達其 monthly_limit 上限(訊息內含上限次數) | {"error":{"code":"quota_exceeded","message":"已超過本月用量上限(1 次)"}} |
key_required/invalid_api_key 為 401、quota_exceeded 為 429),與錯誤碼一節中其餘 400 類參數錯誤不同——請以 code 判斷錯誤種類。用量上限只在該金鑰設有 monthly_limit(非 null)時才會觸發 429。
查詢目前金鑰當月的用量摘要。此端點一定需要金鑰(即使在 open 模式;匿名用量無從歸戶),且本身不計費、不翻譯(回應無詞彙欄位)。也接受 ?lang=,但只影響錯誤訊息的語言(如 key_required/invalid_api_key),不影響資料內容。
請求範例
curl -s https://your-host/api/v1/usage \
-H "Authorization: Bearer ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ"
回應 200(實際輸出)
{
"data": {
"key": {
"prefix": "ak_7hgEJAyQ",
"label": "Acme Web App",
"tier": "free"
},
"month": "2026-07",
"total": 5,
"monthly_limit": 1000,
"remaining": 995,
"by_endpoint": {
"charts": 2,
"cities": 2,
"synastry": 1
},
"by_day": {
"2026-07-25": 5
}
}
}
| 欄位 | 型別 | 說明 |
|---|---|---|
key.prefix | string | 金鑰前綴(ak_ + 8 碼,共 11 字),可安全顯示;完整金鑰不會回傳 |
key.label | string | 建立金鑰時給的標籤 |
key.tier | string | 方案級別(如 free/pro,僅為標記) |
month | string | 統計月份 YYYY-MM(UTC) |
total | integer | 本月總計費呼叫數 |
monthly_limit | integer | null | 每月上限;null 表示無上限 |
remaining | integer | null | 本月剩餘可用次數(max(limit − total, 0));無上限時為 null |
by_endpoint | object | 各端點呼叫數(端點名為去掉 /api/v1/ 前綴的鍵,如 charts),依次數由多到少排序 |
by_day | object | 本月各日(YYYY-MM-DD)呼叫數,依日期升冪排序 |
# Authorization: Bearer(本命盤)
curl -s -X POST https://your-host/api/v1/charts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ" \
-d '{"birth_date":"1990-01-01","birth_time":"12:00","latitude":25.033,"longitude":121.5654,"timezone":"Asia/Taipei"}'
# X-API-Key 標頭(城市搜尋)
curl -s "https://your-host/api/v1/cities?q=tai" \
-H "X-API-Key: ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ"
# 查詢參數 ?api_key=(城市搜尋)
curl -s "https://your-host/api/v1/cities?q=tokyo&api_key=ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ"
不需要管理權杖,任何人都能自助申請一把免費 API 金鑰。流程採雙重確認(double opt-in),分兩步:
POST /api/v1/signup 送出你的 email。系統暫存一筆待確認申請並寄出一封含確認連結的信。此步驟不會回傳金鑰。GET /verify?token=…),在該頁按下確認鈕,前端即以該 token 呼叫 POST /api/v1/verify,此時才簽發並只顯示一次明文金鑰。整個流程公開、免費、不計費、免金鑰。金鑰本身也是免費的;email 這一步只是為了確認你對該信箱的擁有權。取得金鑰後如何傳遞、如何查詢用量,見驗證與用量。另有兩個公開 HTML 頁面:GET /signup(申請頁)與 GET /verify(信件連結的到達頁,內含確認鈕)。
RESEND_API_KEY,信件不會真的寄出,而是把連結寫入伺服器日誌(「logged 模式」),本地與測試環境下整條雙重確認流程仍可運作。
暫存一筆待確認申請並寄出確認連結。公開端點、不計費、免金鑰。防濫用:同一來源 IP(Fly 會設定的 X-Forwarded-For 第一段)每日申請次數達 SIGNUP_DAILY_IP_LIMIT(預設 5)時回 429 signup_rate_limited。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
email | string | 是 | 開發者的電子郵件。格式無效或長度 > 254 字回 400 invalid_email;拋棄式(暫時)信箱網域(如 mailinator.com)回 400 disposable_email | "dev@example.com" |
lang | string | 否 | 錯誤訊息與確認信的語言(見多語言) | "zh-TW" |
請求範例
{
"email": "dev@example.com"
}
回應 202(實際輸出)
{
"data": {
"status": "verification_sent",
"email": "dev@example.com"
}
}
GET /verify?token=…)的有效期為 24 小時,逾期需重新申請。
| HTTP | code | 觸發條件 | 回應範例 |
|---|---|---|---|
| 400 | invalid_email | email 格式無效,或長度超過 254 字 | {"error":{"code":"invalid_email","message":"電子郵件格式無效"}} |
| 400 | disposable_email | email 屬於拋棄式(暫時)信箱網域(如 mailinator.com) | {"error":{"code":"disposable_email","message":"拋棄式(暫時)信箱不予受理,請改用常用信箱"}} |
| 429 | signup_rate_limited | 同一來源 IP 當日申請次數達上限 | {"error":{"code":"signup_rate_limited","message":"今日申請次數過多,請明日再試"}} |
以確認信連結中的 token 確認信箱擁有權,成功時簽發並回傳明文金鑰(只回傳這一次)。一般使用者是經由 GET /verify?token=… 頁面按下確認鈕,由該頁前端 POST 此端點;也可直接以程式呼叫。公開端點、不計費、免金鑰。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
token | string | 是 | 確認信連結(/verify?token=…)中的一次性 token | "3f9c…" |
lang | string | 否 | 錯誤訊息語言(見多語言) | "zh-TW" |
請求範例
{
"token": "3f9c1e7a8b2d4f60a1c3e5d7b9f0a2c4"
}
回應 201(實際輸出,明文 token 只回傳這一次)
{
"data": {
"token": "ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ",
"prefix": "ak_7hgEJAyQ",
"monthly_limit": null,
"tier": "free"
}
}
token(即 API 金鑰)只在此回傳這一次(伺服器只保存其 SHA-256 雜湊),之後任何端點都不會再吐出完整金鑰——請當場保存。新金鑰 tier 為 free,monthly_limit 預設為 null(無上限,除非營運者設定 SIGNUP_MONTHLY_LIMIT)。一次性 token 一經成功使用即失效。
| HTTP | code | 觸發條件 | 回應範例 |
|---|---|---|---|
| 400 | verification_invalid | token 不存在或已使用過 | {"error":{"code":"verification_invalid","message":"驗證連結無效或已使用過"}} |
| 400 | verification_expired | 連結已逾 24 小時過期 | {"error":{"code":"verification_expired","message":"驗證連結已過期,請重新申請"}} |
確認服務狀態與底層 astro_chart gem 版本。
回應 200
{"status":"ok","gem_version":"0.3.0"}
依出生資料計算完整本命盤:上升點、行星位置(含逆行標記、福點、莉莉絲)、宮位(Placidus 或整宮制)、相位、相位圖形(大三角/T三角/大十字)、元素統計。
即為一個出生資料物件(5 個必填欄位 + 選填 house_system)。
請求範例
{
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei",
"house_system": "P"
}
回應 200(實際輸出,planets/houses 節錄)
{
"data": {
"input": {
"birth_date": "1990-01-01",
"birth_time": "12:00",
"coordinates": { "latitude": 25.033, "longitude": 121.5654 },
"timezone": "Asia/Taipei"
},
"chart": {
"ascendant": { "zodiac": "牡羊座", "degree": 16.4422, "total_degree": 16.4422 },
"house_system": "P",
"planets": [
{
"planet": "太陽",
"zodiac": "摩羯座",
"house": 9,
"degree": 10.4744,
"total_degree": 280.4744,
"retrograde": false,
"aspects": [
{ "planet": "木星", "aspect_type": "對分相", "orb": 5.28 },
{ "planet": "土星", "aspect_type": "合相", "orb": 5.14 },
{ "planet": "天王星", "aspect_type": "合相", "orb": 4.71 },
{ "planet": "海王星", "aspect_type": "合相", "orb": 1.55 }
]
},
{
"planet": "水星",
"zodiac": "摩羯座",
"house": 10,
"degree": 25.76,
"total_degree": 295.76,
"retrograde": true
},
// …月亮、金星、火星、木星、土星、天王星、海王星、冥王星、
// 北交點、南交點省略(12 個實體星體/交點)
{
"planet": "福點",
"zodiac": "雙子座",
"house": 2,
"degree": 4.7564,
"total_degree": 64.7564,
"retrograde": false
},
{
"planet": "莉莉絲",
"zodiac": "天蠍座",
"house": 7,
"degree": 6.4703,
"total_degree": 216.4703,
"retrograde": false
},
{
"planet": "北交點定位星",
"ruling_planet": "天王星",
"zodiac": "摩羯座",
"house": 9,
"degree": 5.7656,
"total_degree": 275.7656,
"aspects": [
{ "planet": "太陽", "aspect_type": "合相", "orb": 4.71 },
{ "planet": "木星", "aspect_type": "對分相", "orb": 0.57 }
// …其餘 2 筆省略
],
"retrograde": false
}
// …南交點定位星、上升星座定位星省略(planets 共 17 筆,見「回應欄位說明」)
],
"houses": [
{ "house_number": 1, "degree": 16.4422, "zodiac": "牡羊座" },
{ "house_number": 2, "degree": 50.317, "zodiac": "金牛座" }
// …其餘 10 筆省略,共 12 宮
],
"patterns": [],
"element_stats": {
"elements": { "火": 1, "土": 5, "風": 2, "水": 2 },
"modalities": { "基本": 6, "固定": 3, "變動": 1 }
}
}
}
}
帶 "house_system": "W" 時,宮首固定落在每個星座 0°(第 1 宮 = 上升星座的 0°),ascendant 本身與 Placidus 完全相同。實際輸出節錄(同一筆出生資料):
{
"chart": {
"ascendant": { "zodiac": "牡羊座", "degree": 16.4422, "total_degree": 16.4422 },
"house_system": "W",
"houses": [
{ "house_number": 1, "degree": 0.0, "zodiac": "牡羊座" },
{ "house_number": 2, "degree": 30.0, "zodiac": "金牛座" },
{ "house_number": 3, "degree": 60.0, "zodiac": "雙子座" }
// …其餘 9 筆省略,每宮 +30°
]
// …planets/patterns/element_stats 結構相同(行星宮位依整宮制重新歸宮)
}
}
patterns 多數星盤為空陣列;以 1999-08-11(著名的日食大十字)為例,實際輸出:
"patterns": [
{ "pattern_type": "T三角", "planets": ["水星", "海王星", "木星"], "apex": "木星" },
{ "pattern_type": "大十字", "planets": ["天王星", "太陽", "土星", "火星"] },
{ "pattern_type": "大十字", "planets": ["南交點", "太陽", "土星", "火星"] }
// …共 5 組大十字,此處省略 3 組
]
計算兩人的本命盤,以及兩張盤之間的相位與「A 的行星落入 B 的宮位」對照。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
a | object | 是 | A 的出生資料物件(可含 house_system) | {"birth_date": …} |
b | object | 是 | B 的出生資料物件 | {"birth_date": …} |
orb_limit | number | null | 否 | 跨盤相位的容許度上限(度)。省略或 null 時使用本命盤預設容許度(合相 15° 等,見下方);合盤實務常用較緊的 6.0。必須為 JSON 數字或 null,其他型別回 400 missing_param | 6.0 |
請求範例
{
"a": {
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"b": {
"birth_date": "1992-06-15",
"birth_time": "08:30",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"orb_limit": 6.0
}
回應 200(實際輸出,節錄)
{
"data": {
"a_chart": { /* A 的完整本命盤,結構同 /api/v1/charts 的 data */ },
"b_chart": { /* B 的完整本命盤 */ },
"synastry": {
"aspects": [
{ "a_planet": "冥王星", "b_planet": "天王星", "aspect_type": "六分相", "orb": 0.16 },
{ "a_planet": "太陽", "b_planet": "水星", "aspect_type": "對分相", "orb": 0.19 },
{ "a_planet": "冥王星", "b_planet": "海王星", "aspect_type": "六分相", "orb": 1.13 }
// …其餘筆數省略;一律依 orb 由小到大排序
],
"a_planets_in_b_houses": {
"太陽": 6, "月亮": 7, "水星": 6, "金星": 6, "火星": 5, "木星": 11,
"土星": 6, "天王星": 5, "海王星": 6, "冥王星": 4, "北交點": 7
},
"b_planets_in_a_houses": {
"太陽": 3, "月亮": 9, "水星": 3, "金星": 3, "火星": 1, "木星": 5,
"土星": 11, "天王星": 10, "海王星": 10, "冥王星": 8, "北交點": 9
}
}
}
}
aspects 中每筆的 a_planet 屬於 A、b_planet 屬於 B;a_planets_in_b_houses 表示 A 的行星落入 B 的第幾宮(反之亦然)。合盤比較固定使用 11 個星體(太陽~冥王星+北交點);南交點不參與(恆與北交點正對分,只會鏡射北交點的相位)。福點、莉莉絲與定位星點位也不參與兩張盤的比較。
計算某一時刻(預設為「現在」)天上行星的位置、其落入本命盤的宮位,以及行運行星對本命行星的相位。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
natal | object | 是 | 本命出生資料物件(可含 house_system,影響行運行星歸入哪一宮) | {"birth_date": …} |
at | object | 否 | 行運時刻。省略時使用伺服器當下的 UTC 時間。若提供,三個子欄位皆必填 | {"date": …} |
at.date | string | 是* | 日期 YYYY-MM-DD(驗證規則同 birth_date) | "2026-07-24" |
at.time | string | 是* | 時間 HH:MM(驗證規則同 birth_time) | "12:00" |
at.timezone | string | 是* | IANA 時區識別碼(at.date/at.time 視為此時區的當地時間) | "Asia/Taipei" |
orb_limit | number | 否 | 行運相位容許度上限(度),預設 3.0(行運實務用緊容許度) | 3 |
* 僅在有提供 at 物件時必填。
請求範例
{
"natal": {
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"at": { "date": "2026-07-24", "time": "12:00", "timezone": "Asia/Taipei" },
"orb_limit": 3
}
回應 200(實際輸出,節錄)
{
"data": {
"natal_chart": { /* 完整本命盤,結構同 /api/v1/charts 的 data */ },
"transit_time_utc": "2026-07-24T04:00:00Z",
"planets": [
{
"planet": "太陽",
"zodiac": "獅子座",
"degree": 1.3043,
"total_degree": 121.3043,
"natal_house": 4
},
{
"planet": "月亮",
"zodiac": "射手座",
"degree": 1.4324,
"total_degree": 241.4324,
"natal_house": 8
}
// …其餘 10 筆省略,共 12 筆(太陽~冥王星+北交點+南交點)
],
"aspects": [
{ "transit_planet": "金星", "natal_planet": "土星", "aspect_type": "三分相", "orb": 0.18 },
{ "transit_planet": "水星", "natal_planet": "土星", "aspect_type": "對分相", "orb": 0.7 },
{ "transit_planet": "水星", "natal_planet": "冥王星", "aspect_type": "三分相", "orb": 0.77 },
{ "transit_planet": "海王星", "natal_planet": "木星", "aspect_type": "四分相", "orb": 0.85 }
// …其餘筆數省略;依 orb 由小到大排序
]
}
}
transit_time_utc 為行運時刻換算成 UTC 的 ISO 8601 字串。planets[].natal_house 是行運行星落入本命宮位的宮號。相位比較固定使用 11 個星體(南交點不參與,理由同合盤);行運相位無視本命盤中的福點/莉莉絲/定位星。若 at 時刻落在日光節約時間切換區間,回 400 invalid_time。
「一天推一年」:目標日期距出生每滿一年,推運盤即取出生後一天的天象。回傳推運行星位置(落入本命宮位)與推運行星對本命行星的相位。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
natal | object | 是 | 本命出生資料物件(可含 house_system) | {"birth_date": …} |
target_date | string | 是 | 推運目標日期 YYYY-MM-DD。目標時刻取「同一出生時間+出生時區」,讓整年乾淨地換算 | "2026-07-24" |
orb_limit | number | 否 | 推運相位容許度上限(度),預設 1.0(推運移動極慢,只看極精準的相位) | 1 |
請求範例
{
"natal": {
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"target_date": "2026-07-24",
"orb_limit": 1
}
回應 200(實際輸出,節錄)
{
"data": {
"natal_chart": { /* 完整本命盤,結構同 /api/v1/charts 的 data */ },
"progression": {
"progressed_jd": 2447929.2259389306,
"years_elapsed": 36.56,
"planets": [
{
"planet": "太陽",
"zodiac": "水瓶座",
"degree": 17.6684,
"total_degree": 317.6684,
"natal_house": 11
}
// …其餘 11 筆省略,共 12 筆(結構同行運的 planets)
],
"aspects_to_natal": [
{ "progressed_planet": "火星", "natal_planet": "天王星", "aspect_type": "合相", "orb": 0.11 },
{ "progressed_planet": "北交點", "natal_planet": "北交點", "aspect_type": "合相", "orb": 0.37 },
{ "progressed_planet": "太陽", "natal_planet": "冥王星", "aspect_type": "四分相", "orb": 0.58 }
// …其餘筆數省略;依 orb 由小到大排序
]
}
}
}
progressed_jd 為推運時刻的儒略日(Julian Day)、years_elapsed 為出生至目標日期經過的年數(四捨五入至小數 2 位)。若目標日期的出生時刻在該時區不存在或不唯一(日光節約切換),回 400 invalid_time。
找出指定年份中「行運太陽回到本命太陽經度」的精確時刻(牛頓迭代,精度約 10 秒內),並以該時刻起一張完整的回歸盤。可選擇改用其他地點(回歸移置)。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
natal | object | 是 | 本命出生資料物件(可含 house_system,只影響 natal_chart) | {"birth_date": …} |
year | integer | 是 | 回歸年份。必須為 JSON 整數(字串或小數回 400 missing_param);超出 1885–2099 回 400 date_out_of_range | 2026 |
latitude | number | 否 | 回歸地點緯度(省略時用本命座標)。範圍 −90 ~ 90 | 35.6762 |
longitude | number | 否 | 回歸地點經度(省略時用本命座標)。範圍 −180 ~ 180 | 139.6503 |
timezone | string | 否 | 回歸地點時區(IANA)。僅供顯示(回傳於 location),不影響計算 — 回歸時刻本身是 UTC 定義的 | "Asia/Tokyo" |
請求範例
{
"natal": {
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"year": 2026
}
回應 200(實際輸出,節錄)
{
"data": {
"natal_chart": { /* 完整本命盤,結構同 /api/v1/charts 的 data */ },
"solar_return": {
"return_jd": 2461041.407478858,
"return_time_utc": "2025-12-31T21:46:46Z",
"location": {
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei"
},
"chart": {
"ascendant": { "zodiac": "射手座", "degree": 27.3962, "total_degree": 267.3962 },
"planets": [
{
"planet": "太陽",
"zodiac": "摩羯座",
"house": 1,
"degree": 10.4744,
"total_degree": 280.4744,
"aspects": [
{ "planet": "金星", "aspect_type": "合相", "orb": 1.38 },
{ "planet": "北交點", "aspect_type": "六分相", "orb": 0.5 }
// …其餘筆數省略
]
}
// …其餘 14 筆省略(回歸盤 planets 共 15 筆,見下方注意事項)
],
"houses": [ /* 12 筆宮首,結構同本命盤 houses */ ]
}
}
}
}
2025-12-31T21:46:46Z):迭代從該年份的生日正午出發,找最近的太陽回歸瞬間,生日在年初或年尾時屬正常現象。
solar_return.chart 沿用舊版盤面結構 — planets 共 15 筆(12 星體/交點+3 定位星點位),不含 retrograde、福點、莉莉絲、house_system、patterns、element_stats,宮位固定使用 Placidus。同一回應中的 natal_chart 則是新版 17 筆完整結構。
帶 latitude/longitude/timezone 覆寫時,回歸時刻不變(太陽經度與地點無關),但回歸盤的上升點與宮位改以新地點計算。實際輸出節錄:
"solar_return": {
"return_time_utc": "2025-12-31T21:46:46Z",
"location": { "latitude": 35.6762, "longitude": 139.6503, "timezone": "Asia/Tokyo" }
// …chart 改以東京座標起盤
}
兩張本命盤的中點盤:每個星體取兩盤經度的短弧中點(350° 與 10° 的中點是 0°,不是 180°),再計算中點位置彼此之間的相位。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
a | object | 是 | A 的出生資料物件(可含 house_system) | {"birth_date": …} |
b | object | 是 | B 的出生資料物件 | {"birth_date": …} |
請求範例
{
"a": {
"birth_date": "1990-01-01", "birth_time": "12:00",
"latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei"
},
"b": {
"birth_date": "1992-06-15", "birth_time": "08:30",
"latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei"
}
}
回應 200(實際輸出,節錄)
{
"data": {
"a_chart": { /* A 的完整本命盤,結構同 /api/v1/charts 的 data */ },
"b_chart": { /* B 的完整本命盤 */ },
"composite": {
"planets": [
{ "planet": "太陽", "zodiac": "牡羊座", "degree": 2.3199, "total_degree": 2.3199 },
{ "planet": "月亮", "zodiac": "摩羯座", "degree": 25.4433, "total_degree": 295.4433 }
// …其餘 10 筆省略,共 12 筆(太陽~冥王星+北交點+南交點)
],
"aspects": [
{ "planet_a": "北交點", "planet_b": "南交點", "aspect_type": "對分相", "orb": 0.0 },
{ "planet_a": "金星", "planet_b": "海王星", "aspect_type": "四分相", "orb": 0.28 },
{ "planet_a": "太陽", "planet_b": "土星", "aspect_type": "六分相", "orb": 0.39 }
// …其餘筆數省略;依 orb 由小到大排序
]
}
}
}
orb_limit 參數)。
供出生地輸入使用的城市座標/時區查詢。內建約 160 筆城市:台灣全部 22 縣市(縣治座標)+世界主要城市,支援中文名與英文/拼音別名。
| 名稱 | 型別 | 必填 | 說明 | 範例 |
|---|---|---|---|---|
q | string | 是 | 關鍵字,不分大小寫。前綴符合優先於子字串符合;最多回傳 10 筆。缺少或空白回 400 missing_param | tai、東京、tokyo |
lang | string | 否 | 回應語言(見多語言)。en/ja/ko 時 name/country 改為英文名(如 台北市 → Taipei);不影響比對邏輯 | en |
回應 200(GET /api/v1/cities?q=tai 實際輸出)
{
"data": [
{ "name": "台北市", "country": "台灣", "latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei" },
{ "name": "台中市", "country": "台灣", "latitude": 24.1477, "longitude": 120.6736, "timezone": "Asia/Taipei" },
{ "name": "台南市", "country": "台灣", "latitude": 22.9999, "longitude": 120.2269, "timezone": "Asia/Taipei" },
{ "name": "嘉義縣", "country": "台灣", "latitude": 23.4518, "longitude": 120.2555, "timezone": "Asia/Taipei" },
{ "name": "台東縣", "country": "台灣", "latitude": 22.7583, "longitude": 121.1444, "timezone": "Asia/Taipei" },
{ "name": "新北市", "country": "台灣", "latitude": 25.012, "longitude": 121.4657, "timezone": "Asia/Taipei" }
]
}
q 開頭」的城市,再列出「名稱或別名包含 q」的城市(如上例:嘉義縣因別名 Taibao 前綴符合而排在僅子字串符合的新北市之前)。查無結果時回傳 {"data":[]}(HTTP 200)。
chart.planets[])| 欄位 | 型別 | 說明 |
|---|---|---|
planet | string | 行星/點位名稱(中文) |
zodiac | string | 所在星座(12 星座中文名,例如 摩羯座) |
house | integer | 所在宮位(1–12,依所選宮位制) |
degree | number | 在該星座內的度數(0–30) |
total_degree | number | 黃道絕對經度(0–360,牡羊座 0° 起算) |
retrograde | boolean | 是否逆行。太陽/月亮恆為 false;南交點與北交點同值;福點/莉莉絲/定位星點位恆為 false(非實體天體) |
aspects | array | 與其他行星形成的相位清單(僅特定行星帶有此欄位,見下)。每筆含 planet(對象)、aspect_type、orb(偏差度數) |
ruling_planet | string | 僅三個「定位星」點位帶有此欄位:實際擔任定位星的行星名稱 |
太陽、月亮、水星、金星、火星、木星、土星、天王星、海王星、冥王星、北交點、南交點福點(Part of Fortune:日盤 ASC+月−日、夜盤 ASC−月+日;日夜以太陽是否在地平線上判定)、莉莉絲(平均黑月莉莉絲=平均月亮遠地點)北交點定位星、南交點定位星、上升星座定位星(各帶 ruling_planet 欄位,位置即其定位星行星的位置)aspects 欄位只出現在:太陽、月亮、金星、土星、北交點、南交點,以及三個定位星點位。其餘(水星、火星、木星、天王星、海王星、冥王星、福點、莉莉絲)不帶 aspects。
chart.house_system)| 值 | 宮位制 | 說明 |
|---|---|---|
"P" | Placidus(普拉西德) | 預設。宮首依半弧迭代計算;極區(約 |緯度| ≥ 66°)無定義,回 400 polar_latitude |
"W" | Whole Sign(整宮制) | 第 1 宮=上升星座整個星座(宮首 = 該星座 0°),其後每宮 +30°。上升點計算與 Placidus 相同;極區緯度也可計算 |
chart.patterns[])從 12 個星體/交點的位置偵測三種經典圖形;無圖形時為空陣列 []。
pattern_type | 組成 | 額外欄位 |
|---|---|---|
大三角 | 3 星兩兩三分相 | element:三星同元素時為 "火"/"土"/"風"/"水",否則 null |
T三角 | 2 星對分相,兩者皆四分相於端點星 | apex:端點星名稱 |
大十字 | 4 星構成 2 組對分相、相鄰皆四分相 | — |
每筆皆含 planets(組成星體名稱陣列)。去重規則:大十字會吸收其自身 4 星構成的 T三角(不重複回報);北交點—南交點這組「定義上的對分相」不作為 T三角/大十字的對分軸(但交點仍可作為端點星等其他角色);由於南交點恆與北交點正對,對分相被交點軸四分時只回報一筆 T三角(端點星為北交點),不會出現北/南交點鏡像的重複組。
chart.element_stats)統計 10 個古典行星(太陽~冥王星,不含交點與衍生點)落入星座的元素與模式分布,兩組計數各自加總為 10:
"element_stats": {
"elements": { "火": 1, "土": 5, "風": 2, "水": 2 },
"modalities": { "基本": 6, "固定": 3, "變動": 1 }
}
對應規則:牡羊=火/基本、金牛=土/固定、雙子=風/變動⋯依序循環(元素每 4 個星座一輪、模式每 3 個星座一輪)。
| 相位 | 角度 | 最大容許度 |
|---|---|---|
| 合相 | 0° | 15° |
| 六分相 | 60° | 6° |
| 四分相 | 90° | 8° |
| 三分相 | 120° | 8° |
| 對分相 | 180° | 10° |
回應中的 orb 為實際角度與準確相位角的偏差(度,四捨五入至小數 2 位),數值越小相位越緊密。行運(預設 3°)與推運(預設 1°)另以 orb_limit 過濾。
chart.ascendant:上升點,含 zodiac、degree(星座內度數)、total_degree(黃道絕對經度)。P/W 兩制的上升點相同。chart.houses:12 筆宮首資料,每筆含 house_number(1–12)、degree(宮首的黃道絕對經度 0–360)、zodiac(宮首星座)。所有錯誤皆回傳 JSON,格式為:
{ "error": { "code": "<code>", "message": "<訊息(預設中文,依 lang 在地化)>" } }
message 會依請求的 lang 在地化(見多語言;主體無法解析或 lang 本身無效時固定 zh-TW);code 與語言無關,下表範例皆為預設 zh-TW 訊息。大多數參數錯誤為 HTTP 400,但金鑰相關錯誤帶不同狀態(key_required/invalid_api_key 為 401、quota_exceeded 為 429)——請務必以 code 而非 HTTP 狀態或訊息文字判斷錯誤種類。
| HTTP | code | 觸發條件 | 回應範例 |
|---|---|---|---|
| 400 | invalid_json | 主體不是合法 JSON 或不是 JSON 物件 | {"error":{"code":"invalid_json","message":"無效的 JSON 格式"}} |
| 400 | missing_param | 缺少必填欄位(含 a/b/natal 物件、target_date、at.* 子欄位、q)、orb_limit 不是數字/null,或 year 不是整數 | {"error":{"code":"missing_param","message":"缺少參數:birth_date"}} |
| 400 | invalid_date | birth_date/at.date/target_date 格式錯誤或非有效日期 | {"error":{"code":"invalid_date","message":"無效的出生日期,格式須為 YYYY-MM-DD"}} |
| 400 | invalid_time | birth_time/at.time 格式錯誤、超出 0–23 / 0–59,或該時刻(含推運目標日期的出生時刻)落在日光節約時間切換的無效/不明確區間 | {"error":{"code":"invalid_time","message":"無效的出生時間,格式須為 HH:MM"}} |
| 400 | invalid_coordinates | 緯度/經度非數字或超出範圍(字串一律拒絕;含太陽回歸的地點覆寫) | {"error":{"code":"invalid_coordinates","message":"無效的座標:緯度須在 ±90、經度須在 ±180 之間"}} |
| 400 | invalid_timezone | timezone/at.timezone 非有效 IANA 識別碼 | {"error":{"code":"invalid_timezone","message":"無效的時區識別碼:Asia/Tokio"}} |
| 400 | invalid_house_system | house_system 不是 P/placidus/W/whole_sign(不分大小寫) | {"error":{"code":"invalid_house_system","message":"無效的宮位制式:K(支援 P / placidus 或 W / whole_sign)"}} |
| 400 | invalid_lang | lang 不是支援的語言(zh-TW/zh-tw/zh_tw/zh/en/ja/ko,不分大小寫;空字串也算無效)。此錯誤訊息固定為 zh-TW | {"error":{"code":"invalid_lang","message":"不支援的語言:fr(支援 zh-TW / en / ja / ko)"}} |
| 400 | polar_latitude | 極區緯度(約 |緯度| ≥ 66°)使 Placidus 宮位無解(整宮制 W 不受此限) | {"error":{"code":"polar_latitude","message":"極區緯度無法計算 Placidus 宮位"}} |
| 400 | date_out_of_range | 任一計算時刻(出生日期、行運 at、推運目標、回歸年份)超出冥王星可計算範圍(1885–2099) | {"error":{"code":"date_out_of_range","message":"日期超出可計算範圍(1885–2099)"}} |
| 401 | key_required | 需要 API 金鑰但未提供(required 模式的計費端點,或任何模式的 /usage)。詳見驗證與用量 | {"error":{"code":"key_required","message":"此端點需要 API 金鑰"}} |
| 401 | invalid_api_key | 提供的金鑰不存在或已被撤銷 | {"error":{"code":"invalid_api_key","message":"API 金鑰無效或已撤銷"}} |
| 429 | quota_exceeded | 該金鑰本月用量已達 monthly_limit 上限(訊息含上限次數) | {"error":{"code":"quota_exceeded","message":"已超過本月用量上限(1 次)"}} |
| 400 | invalid_email | 自助申請的 email 格式無效或長度 > 254 字(POST /api/v1/signup) | {"error":{"code":"invalid_email","message":"電子郵件格式無效"}} |
| 400 | disposable_email | 自助申請使用拋棄式(暫時)信箱網域(POST /api/v1/signup) | {"error":{"code":"disposable_email","message":"拋棄式(暫時)信箱不予受理,請改用常用信箱"}} |
| 429 | signup_rate_limited | 同一來源 IP 當日自助申請次數達上限(POST /api/v1/signup) | {"error":{"code":"signup_rate_limited","message":"今日申請次數過多,請明日再試"}} |
| 400 | verification_invalid | 確認 token 不存在或已使用過(POST /api/v1/verify) | {"error":{"code":"verification_invalid","message":"驗證連結無效或已使用過"}} |
| 400 | verification_expired | 確認連結已逾 24 小時過期(POST /api/v1/verify) | {"error":{"code":"verification_expired","message":"驗證連結已過期,請重新申請"}} |
| 404 | not_found | 不存在的 /api 路徑 | {"error":{"code":"not_found","message":"找不到此 API 路徑"}} |
| 500 | internal_error | 未預期的伺服器錯誤(不洩漏堆疊資訊) | {"error":{"code":"internal_error","message":"伺服器內部錯誤,請稍後再試"}} |
at.* 與推運 target_date 的驗證沿用出生欄位的驗證器,因此錯誤訊息會寫作「出生日期/出生時間」——請以 code 判斷錯誤種類,勿依賴訊息文字。
P)與整宮制(W),無其他宮位制可選。polar_latitude;改用 house_system: "W" 可正常計算。date_out_of_range。Asia/Taipei、America/New_York),不接受 UTC+8、CST 之類的縮寫或偏移格式。curl -s -X POST https://your-host/api/v1/charts \
-H "Content-Type: application/json" \
-d '{
"birth_date": "1990-01-01",
"birth_time": "12:00",
"latitude": 25.033,
"longitude": 121.5654,
"timezone": "Asia/Taipei",
"house_system": "W"
}'
curl -s -X POST https://your-host/api/v1/synastry \
-H "Content-Type: application/json" \
-d '{
"a": {"birth_date": "1990-01-01", "birth_time": "12:00",
"latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei"},
"b": {"birth_date": "1992-06-15", "birth_time": "08:30",
"latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei"},
"orb_limit": 6.0
}'
curl -s -X POST https://your-host/api/v1/transits \
-H "Content-Type: application/json" \
-d '{
"natal": {"birth_date": "1990-01-01", "birth_time": "12:00",
"latitude": 25.033, "longitude": 121.5654, "timezone": "Asia/Taipei"}
}'
const res = await fetch("/api/v1/charts", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
birth_date: "1990-01-01",
birth_time: "12:00",
latitude: 25.033,
longitude: 121.5654,
timezone: "Asia/Taipei",
}),
});
const json = await res.json();
if (!res.ok) throw new Error(`${json.error.code}: ${json.error.message}`);
console.log(json.data.chart.ascendant); // { zodiac: "牡羊座", degree: 16.4422, … }
const retro = json.data.chart.planets.filter(p => p.retrograde);
console.log(retro.map(p => p.planet)); // ["水星", "金星", "木星"]
require "net/http"
require "json"
uri = URI("https://your-host/api/v1/charts")
res = Net::HTTP.post(
uri,
{
birth_date: "1990-01-01",
birth_time: "12:00",
latitude: 25.033,
longitude: 121.5654,
timezone: "Asia/Taipei",
}.to_json,
"Content-Type" => "application/json"
)
json = JSON.parse(res.body)
if res.is_a?(Net::HTTPSuccess)
sun = json.dig("data", "chart", "planets").find { |p| p["planet"] == "太陽" }
puts "太陽:#{sun["zodiac"]} #{sun["degree"]} 度(第 #{sun["house"]} 宮)"
puts "元素分布:#{json.dig("data", "chart", "element_stats", "elements")}"
else
warn "#{json.dig("error", "code")}: #{json.dig("error", "message")}"
end
/admin/api-keys、/admin/usage 端點都由伺服器機密 ADMIN_TOKEN 保護,用來簽發/撤銷 API 金鑰與檢視全站用量。
驗證方式:以 Authorization: Bearer <ADMIN_TOKEN> 傳入伺服器設定的密鑰(與 API 金鑰無關,是另一組營運機密)。
| HTTP | code | 觸發條件 | 回應範例 |
|---|---|---|---|
| 503 | admin_disabled | 伺服器未設定 ADMIN_TOKEN(管理 API 整個停用) | {"error":{"code":"admin_disabled","message":"管理介面未啟用"}} |
| 401 | admin_unauthorized | 提供的 ADMIN_TOKEN 錯誤 | {"error":{"code":"admin_unauthorized","message":"管理權杖無效"}} |
請求主體:{"label":"...","tier":"free","monthly_limit":1000|null}(monthly_limit 為 null 表示無上限;須為非負整數或 null)。
回應 201(實際輸出)
{
"data": {
"id": 1,
"token": "ak_7hgEJAyQvsuO4zHntkpoMvnvrecJ_6QJ",
"prefix": "ak_7hgEJAyQ",
"label": "Acme Web App",
"tier": "free",
"monthly_limit": 1000,
"created_at": "2026-07-25T04:55:45Z"
}
}
token 只在建立當下回傳這一次(伺服器只保存其 SHA-256 雜湊),之後任何端點都不會再吐出完整金鑰——請當場保存並交給使用者。
monthly_limit 若為負數或非整數(如字串),回 400,但 code 為 missing_param(訊息為「monthly_limit 必須為非負整數或留空」),並非另一組專屬錯誤碼。label 省略時預設空字串、tier 省略時預設 "free"。
依 id 由新到舊列出所有金鑰,不含 token/雜湊。
回應 200(實際輸出,節錄)
{
"data": [
{
"id": 3, "prefix": "ak_IVRZsXlz", "label": "tiny", "tier": "free",
"monthly_limit": 1, "created_at": "2026-07-25T04:55:45Z", "revoked_at": null
},
{
"id": 1, "prefix": "ak_7hgEJAyQ", "label": "Acme Web App", "tier": "free",
"monthly_limit": 1000, "created_at": "2026-07-25T04:55:45Z", "revoked_at": null
}
// …其餘省略
]
}
revoked_at 為 null 表示金鑰仍有效;已撤銷者帶 UTC 時間字串。
撤銷指定金鑰;撤銷後該金鑰立即失效(之後呼叫回 401 invalid_api_key)。
回應 200(實際輸出)
{ "data": { "id": 1, "revoked": true } }
id(或已撤銷)時回 404,主體為 JSON 錯誤物件 {"error":{"code":"not_found",…}}。
檢視某月(省略 month 時為當月 UTC)的全站用量。by_key 以金鑰 id 為鍵對應該金鑰呼叫數,匿名呼叫歸在 "anonymous"。
回應 200(實際輸出)
{
"data": {
"month": "2026-07",
"total": 7,
"by_endpoint": { "cities": 3, "charts": 3, "synastry": 1 },
"by_key": { "1": 5, "anonymous": 1, "3": 1 }
}
}
另提供一個瀏覽器管理頁面 /admin:這是一個公開的外殼頁(頁面本身免驗證即可載入),會在前端提示輸入 ADMIN_TOKEN,再以該權杖呼叫上述管理 API。實際操作仍受 ADMIN_TOKEN 保護。
完整的機器可讀 API 規格(OpenAPI 3.1,含所有端點的請求/回應 schema 與範例):GET /openapi.json。可直接匯入 Swagger UI、Postman、Insomnia 等工具。