คู่มือ API
หากอยากรู้ว่าสแตก API นี้ทำงานอย่างไรในบริการจริง — ลองใช้การวิเคราะห์ซาจูและการสนทนากับ AI ด้วยตัวเองได้ที่ INTA แอป AI ซาจูที่ขับเคลื่อนด้วยเอนจินเดียวกัน INTA คือข้อมูลอ้างอิงที่มีชีวิตของ API นี้ การตอบกลับด้วยเสียง AI (TTS) ของ INTA ก็ขับเคลื่อนด้วยสแตกเดียวกัน — API เสียงจะเปิดให้ใช้ในภายหลัง
ให้ AI สร้างแอปให้ — อีบุ๊กฟรี
เลือกหนังสือ (ภาษาเกาหลี)แอปดูดวงแบบรวม (ภาษาเกาหลี)แอปแชตกับตัวละคร (ภาษาเกาหลี)เว็บแอประบบสมาชิก (ภาษาเกาหลี)มินิแอป Apps in Toss (ภาษาเกาหลี)
Quickstart
HRUM ให้บริการ AI ที่จดจำได้ การวิเคราะห์ซาจู และการขายต่อ LLM ทำตาม 3 ขั้นตอนต่อไปนี้:
ที่อยู่หลักคือ https://api.hrum.ai (API) · https://console.hrum.ai (คอนโซล) ที่อยู่เดิม api.float.do · console.float.do · api.inta.do ยังใช้งานได้ตามเดิม หากเชื่อมต่อไว้แล้วก็ไม่ต้องเปลี่ยน
- ออกคีย์ API - สมัครสมาชิกคอนโซลแล้วออกคีย์ที่หน้า คีย์ API (คีย์จะแสดงเพียงครั้งเดียวทันทีหลังออก) ขั้นตอนตั้งแต่สมัครสมาชิกจนถึงการจัดการข้อผิดพลาดสรุปไว้ใน คู่มือเริ่มต้นใช้งานสำหรับนักพัฒนา
- ส่งคำขอ - ส่งคำขอ POST ตามตัวอย่างด้านล่าง
- จัดการการตอบกลับ - ดึงข้อมูลซาจูจากการตอบกลับ JSON
curl -X POST https://api.hrum.ai/api/v1/partners/v1/manseryeok \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"year": 1990,
"month": 1,
"day": 15,
"hour": 14,
"minute": 30,
"timezone": "Asia/Seoul",
"gender": "male"
}'
ข้อควรระวังเรื่อง User-Agent: User-Agent เริ่มต้นของไลบรารีมาตรฐาน Python urllib (Python-urllib/3.x) จะติดกฎความปลอดภัยและได้ 403 (error 1010) กลับมา requests, OpenAI SDK, Node, curl ทำงานได้ปกติ หากใช้ urllib หรือ HTTP client ที่เขียนเอง ให้ระบุเฮดเดอร์ User-Agent: <ชื่อแอป>/<เวอร์ชัน> เอง
(วัดจริง: python-requests ผ่าน · OpenAI/Python ผ่าน · node ผ่าน · Python-urllib 403)
ประหยัดค่าใช้จ่าย — เก็บผลลัพธ์ไว้แล้วนำกลับมาใช้ ทุกคำขอที่สำเร็จจะคิดค่าบริการแยกกัน ผลปฏิทินหมื่นปี · จื่อเวยโต่วซู่ · ดวงสมพงษ์ · โหราศาสตร์ตะวันตก · ดวงชะตาตลอดชีวิตที่มีวันเวลาเกิดและตัวเลือกเดียวกันจะได้ผลเหมือนเดิมแม้เรียกใหม่ จึงควรเก็บการตอบกลับแรกลง DB (เช่น ใช้แฮชของเนื้อหาคำขอเป็นคีย์) แล้วใช้ค่าที่เก็บไว้ในครั้งต่อไป สำหรับผลที่เปลี่ยนตามวันที่ เช่น ดวงวันนี้หรือกราฟดวงชะตา ให้ใส่วันที่ลงในคีย์ด้วย รายละเอียดอยู่ที่ Idempotency
ข้อมูลอ้างอิง API
HRUM ให้บริการ AI ที่จดจำได้ การวิเคราะห์ซาจู และการขายต่อ LLM
- เปลี่ยนแปลง (2026-10-14): ปรับสำนวนประโยคตอบกลับภาษาเกาหลีให้เป็นแบบสุภาพ (해요체) เหมือนกันทั้งหมด (ไม่มีการเปลี่ยนเนื้อหาหรือฟิลด์)
- เพิ่ม (2026-10-14): หากไม่รู้จักชื่อเขตเวลา การตอบกลับที่สำเร็จจะมี
warnings(UNKNOWN_TIMEZONE) แนบมา การคำนวณยังใช้เขตเวลาเริ่มต้นเหมือนเดิม และถ้าไม่มีคำเตือน การตอบกลับจะเหมือนเดิม — คำเตือนในการตอบกลับ - เพิ่ม (2026-10-17):
birthของ AI อ่านดวงซาจู · หน่วยความจำการอ่านดวง · รายงาน รับฟิลด์สถานที่เกิด · เขตเวลา · เดือนอธิกมาส (isLeapMonth·timezone· พิกัด ·country·zaSiRule·birthTimePrecision) เหมือนกับ API ปฏิทินหมื่นปี หากไม่ส่ง การคำนวณจะเหมือนเดิม — API AI อ่านดวงซาจู
RIDM Memory API
โฮสต์ความจำการสนทนาแยกตามผู้ใช้ปลายทาง และเพิ่มเลเยอร์หน่วยความจำให้โมเดล ridm/* หน่วยความจำใช้ได้เฉพาะ ridm/* ส่วนโมเดล OpenAI/Google เป็นการขายต่อ (ตามต้นฉบับ) — โมเดลเดียวกัน แต่เป็นสินค้าต่างกัน รองรับการแทรกคำบรรยาย YouTube อัตโนมัติด้วย
ไม่มีเซสชัน — เซสชันไม่จำกัด เมื่อเรียกด้วย user เดียวกัน การสนทนาจะต่อเนื่องไปไม่สิ้นสุด ทุกครั้งที่เรียก เซิร์ฟเวอร์จะแนบเทิร์นสนทนาล่าสุด historyCount เทิร์น และความจำระยะยาว recallCount รายการ (สรุป · โปรไฟล์ · ข้อเท็จจริงที่จำไว้ · เรื่องที่กำลังกังวลอยู่) ให้อัตโนมัติ พาร์ทเนอร์จึงส่งแค่ข้อความใหม่ข้อความเดียว ปรับระยะการอ้างอิงย้อนหลังได้ด้วยตัวเลขสองตัวนี้ และกำหนดเพดานจำนวนข้อความที่เก็บต่อผู้ใช้ปลายทางด้วย memoryCap หากต้องการจัดการประวัติเอง ให้ละ historyCount แล้วใส่บทสนทนาก่อนหน้าใน messages ตามแบบ OpenAI
บทสนทนายาวก็ไม่ทำให้ค่าใช้จ่ายเพิ่มแบบเส้นตรง เทิร์นของผู้ช่วยที่เก่าจะถูกบีบอัดอัตโนมัติ — 2 เทิร์นล่าสุดคงต้นฉบับไว้ ก่อนหน้านั้นจะลดเป็นขั้นจาก 500 ตัวอักษร → 200 ตัวอักษรเพื่อประหยัดโทเค็นขาเข้า (เทิร์นของผู้ใช้คงเดิม) และสำหรับคำถามที่ถามถึงสิ่งที่เคยพูด เช่น "ครั้งก่อนบอกว่า ~ ไม่ใช่เหรอ" เซิร์ฟเวอร์จะค้นหาบทสนทนาจริงที่เก็บไว้แล้วอ้างอิงพร้อมวันที่และผู้พูด (รวมอยู่ใน recalledMemories) — ถ้าไม่มีบันทึกก็จะตอบว่าไม่มี ไม่แต่งขึ้นเอง
LLM API (ขายต่อ) vs RIDM Memory API — ต่างกันอย่างไร
โมเดลเดียวกัน สินค้าต่างกัน — ต่างกันแค่คำนำหน้า ที่เหลือเหมือนกัน หากการตอบกลับมี recalledMemories · memorySaved แนบมา แสดงว่าเป็นเส้นทาง RIDM
| ฟีเจอร์ | LLM API (ขายต่อ) | RIDM Memory API |
|---|---|---|
| การเลือกโมเดล | openai/*, google/*, anthropic/* ฯลฯ |
ridm/* (ใส่คำนำหน้า) |
| รูปแบบการตอบกลับ | การตอบกลับของโมเดลต้นฉบับตามเดิม (เข้ากันได้กับ OpenAI) | โมเดลต้นฉบับ + ฟิลด์หน่วยความจำ |
พารามิเตอร์ user |
ถูกละเว้น | จำเป็น (endUserId, คงความจำไว้) |
| ความจำ · สรุป · การระลึกโปรไฟล์ของบทสนทนา | ✗ | ✓ (recallCount·memoryCap) |
| การประมวลผลเอกสาร | แทรกเฉพาะ fileIds ที่ระบุ |
fileIds ที่ระบุ + ระลึกอัตโนมัติ |
| การจัดการลิงก์ YouTube | รองรับ youtube:true |
รองรับ youtube:true |
วิเคราะห์อารมณ์ (emotion) |
ถูกละเว้น (ยกเว้นบัญชีที่ปิดฟีเจอร์อารมณ์ในคอนโซลแล้วส่ง emotion:true จะได้ 403 FEATURE_DISABLED ไม่ว่าจะเป็นโมเดลใด) |
✓ (รวมรอบการสรุป) |
| การกลั่นกรองเนื้อหา (Moderation) | เฉพาะข้อความ user | ข้อความ system + user |
ข้อจำกัด systemPrompt |
ถูกละเว้น — โมเดลขายต่อจะละเว้น systemPrompt จึงให้ใส่เป็น {"role":"system"} ใน messages |
ตรวจสอบ 8,000 ตัวอักษร (เฉพาะ ridm) |
| ฟิลด์เพิ่มเติมในการตอบกลับ | costUsd, costWon (ค่าใช้จ่าย) |
costWon, recalledMemories, memorySaved, memoryCapReached, filesRecalled, emotion, customProfile |
| ราคา | ต้นทุน × อัตราแลกเปลี่ยน × 1.10 | ราคาขายต่อ × 1.30 (รวมการคงความจำ · การระลึก · อารมณ์ · การระลึกไฟล์อัตโนมัติทั้งหมด ไม่มีค่าบริการเพิ่มแยกตามฟีเจอร์) |
| ข้อยกเว้น | — | ridm/saju-report: ไม่มีหน่วยความจำ → คิดเฉพาะส่วนต่างการขายต่อ ใช้ chat ไม่ได้ (สำหรับรายงานเท่านั้น) |
เปรียบเทียบตัวอย่างโค้ด
// LLM API (resale) — no memory
{
"model": "openai/gpt-5.6-terra",
"messages": [{ "role": "user", "content": "..." }]
}
// RIDM Memory API — with the memory engine
{
"model": "ridm/gpt-5.6-terra", // only the prefix differs
"user": "user_123", // required (keeps memory)
"messages": [{ "role": "user", "content": "..." }]
}
// Difference in the response
// Resale: { "id": "...", "choices": [...], "usage": {...}, "costWon": 1, "costUsd": 0.00045 }
// RIDM: { "id": "...", "choices": [...], "usage": {...}, "costWon": 2, "recalledMemories": [...], "memorySaved": { "id": "turn-...", "keywords": [] } }
POST /api/v1/partners/v1/chat/completions
การเรียก LLM แบบสนทนาที่มีหน่วยความจำ เมื่อเรียกด้วย user/endUserId เดียวกัน บริบทในอดีตจะถูกคงไว้
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
model |
string | O | ชื่อโมเดล RIDM: ridm/gpt-5.6-terra ฯลฯ / ขายต่อ: openai/gpt-5.2, google/gemini-3.5-flash ฯลฯ |
user |
string | O | ID ผู้ใช้ปลายทางที่พาร์ทเนอร์ออกให้ (endUserId — ค่าเดียวกันจะคงความจำไว้) |
messages |
array | O | อาร์เรย์ข้อความรูปแบบ OpenAI [{ "role": "user", "content": "..." }, ...] |
systemPrompt |
string | คำสั่งระบบ (ไม่บังคับ สูงสุด 8,000 ตัวอักษร — เฉพาะ ridm/*) โมเดลขายต่อจะละเว้น systemPrompt จึงให้ใส่เป็น {"role":"system"} ใน messages |
|
youtube |
boolean | หากเป็น true จะแทรกคำบรรยายของลิงก์ YouTube ในข้อความสุดท้ายอัตโนมัติ | |
stream |
boolean | ตอบกลับแบบสตรีมหรือไม่ (ค่าเริ่มต้น: false) ดูรูปแบบได้ที่ รูปแบบสตรีมมิง (SSE) ด้านล่าง — ไม่ใช่รูปแบบ chunk ของ OpenAI | |
fileIds |
string[] | ID เอกสารที่อัปโหลดเพื่อแทรก (UUID สูงสุด 5 รายการ) ดู API ประมวลผลเอกสาร | |
emotion |
boolean | วิเคราะห์สภาวะอารมณ์ (เฉพาะ ridm/* ค่าเริ่มต้น false) ดู วิเคราะห์สภาวะอารมณ์ | |
summaryEvery |
integer | รอบการอัปเดตสรุป · อารมณ์ (หน่วยเป็นเทิร์น 1~20 ค่าเริ่มต้น 5 เฉพาะ ridm/*) | |
temperature |
number | 0~2 จะไม่ส่งต่อให้โมเดลที่ใช้การให้เหตุผลอย่างเดียว (โมเดลที่ปิดการให้เหตุผลไม่ได้) | |
top_p |
number | 0~1 | |
presence_penalty / frequency_penalty |
number | แต่ละค่า -2~2 | |
seed / stop |
number / string|string[] | ส่งต่อไปยังต้นทางด้วยความหมายเดียวกับ OpenAI | |
response_format |
object | รูปแบบ OpenAI (เมื่อใช้ json_object ต้องมีคำว่า "JSON" ใน messages หรือ systemPrompt) โมเดล Claude จะละเว้น |
|
tools / tool_choice / parallel_tool_calls |
array / string|object / boolean | การเรียกฟังก์ชันรูปแบบ OpenAI รองรับโมเดล OpenAI · Google (รวมชื่อเดียวกันที่ขึ้นต้นด้วย ridm/) โมเดล Claude ได้ 400 TOOLS_UNSUPPORTED_FOR_MODEL |
|
n / stream_options |
— | รับไว้เพื่อความเข้ากันได้กับ SDK แต่ละเว้น (ตอบกลับ 1 รายการเสมอ) | |
max_tokens |
number | โทเค็นขาออกสูงสุด (1~8,192 เกินจะได้ 400) โมเดลตระกูล gpt-5.1 ขึ้นไป · 5.4 · 5.5 · 5.6 เซิร์ฟเวอร์จะปิดการให้เหตุผล (reasoning_effort none) แล้วเรียก เนื้อหาจึงออกมาตามที่ขอ โมเดลที่ปิดการให้เหตุผลไม่ได้ (gpt-5 · gpt-5-mini · gpt-5-nano · gpt-6-astra · o3 · o3-mini · o4-mini) เซิร์ฟเวอร์จะเพิ่มงบการให้เหตุผล 1,500 โทเค็นแล้วเรียก และโทเค็นการให้เหตุผลนี้ก็คิดค่าบริการเป็นขาออกด้วย | |
historyCount |
number | จำนวนเทิร์นสนทนาล่าสุดที่เซิร์ฟเวอร์จะแนบให้อัตโนมัติ (1~50) หากระบุ ใน messages ส่งแค่ข้อความใหม่ก็พอ หากละไว้ จะไม่แนบประวัติจากเซิร์ฟเวอร์และใช้เฉพาะ 10 รายการสุดท้ายของ messages |
|
recallCount |
number | จำนวนความจำระยะยาว (สรุปในอดีต) ที่เกี่ยวข้องกับคำถามที่จะระลึก (0~20 ค่าเริ่มต้น 3) โปรไฟล์ · ข้อเท็จจริงที่จำไว้ · เรื่องที่กำลังกังวลอยู่จะรวมไว้เสมอ | |
memoryCap |
number | เพดานอ้างอิงของจำนวนข้อความที่เก็บต่อผู้ใช้ปลายทาง (10~1000 ค่าเริ่มต้น 100) ใช้กับแต่ละคำขอและไม่ถูกบันทึกถาวร หากจำนวนข้อความที่เก็บเกินเพดาน เทิร์นนี้ยังถูกเก็บ แต่การตอบกลับจะมี memoryCapReached: true, memorySaved: null |
|
candor |
string | โทนคำพูด — ระดับความตรงไปตรงมาของคำตอบ t / f (ค่าเริ่มต้น) เฉพาะ ridm/* โมเดลขายต่อจะละเว้น ดู โทนคำพูด (ชื่อชั่วคราว) |
โทนคำพูด (ชื่อชั่วคราว) — candor
แม้เป็นซาจูเดียวกันและคำถามเดียวกัน แต่ละคนก็อยากฟังคำตอบในโทนที่ต่างกัน candor กำหนดว่าคำตอบจะตรงไปตรงมาแค่ไหน ทำงานแบบเดียวกันใน RIDM Memory API (ridm/*) และการอ่านดวงซาจูทั้ง 3 แบบ (การอ่านดวง · หน่วยความจำการอ่านดวง · รายงาน)
f(แบบ F) — ค่าเริ่มต้น ไม่เปลี่ยนอะไรเลย เหมือนกับไม่ได้ส่งฟิลด์นี้t(แบบ T) — คนพูดตรง บอกการตัดสินอย่างตรงไปตรงมาให้ชัดเจนในย่อหน้าแรก และปิดท้ายด้วยสิ่งที่ทำได้ตอนนี้ ไม่ตำหนิตัวบุคคลและไม่ฟันธงแบบชะตากรรมนิยม
ค่าเดิมยังรับได้: blunt → t, balanced · gentle → ปรับเป็น f (gentle ไม่ใช่โทนคำพูดแยกต่างหากอีกต่อไป)
เป็นคนละแกนกับ tone (ภาษาสุภาพ · ภาษากันเอง · ทางการ) จึงใช้ร่วมกันได้ ตัวอย่าง: tone: "formal" + candor: "t" = คำตอบที่สุภาพแต่ตรงไปตรงมา
systemPrompt · persona มีลำดับความสำคัญสูงกว่า หากขัดกับสำนวน · ข้อห้าม · รูปแบบในการตั้งค่าตัวละคร จะยึดตามฝั่งนั้น
หากตรวจพบสัญญาณวิกฤตในข้อความผู้ใช้ (รวมกรณีที่การตรวจความปลอดภัยล้มเหลว) โทนคำพูดจะกลับเป็น f อัตโนมัติ เฉพาะคำขอที่ส่ง candor เป็น t (หรือ blunt) เท่านั้นที่การตอบกลับจะมี candorApplied (ค่าที่ใช้จริง t | f) และในกรณีที่กลับค่าแบบนี้จะแสดงเป็น "f" แม้ส่งด้วยค่าเดิม candorApplied ก็จะคืนค่าเป็น t/f
โทเค็นที่ใช้กับคำสั่งโทนคำพูดไม่คิดค่าบริการ ประวัติการสนทนา (RIDM Memory) จะเก็บเฉพาะต้นฉบับที่ผู้ใช้ส่ง โมเดลขายต่อ (openai/* ฯลฯ) จะละเว้น หากส่งค่าที่ไม่อนุญาต (เช่น "off", "harsh") จะได้ 400 กลับมา
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/chat/completions \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "ridm/gpt-5.6-terra",
"user": "member-1024",
"messages": [
{ "role": "user", "content": "Can we pick up where we left off about changing jobs?" }
]
}'
ตัวอย่างการตอบกลับ
{
"id": "chatcmpl-123",
"object": "chat.completion",
"created": 1629292800,
"model": "ridm/gpt-5.6-terra",
"choices": [
{
"message": {
"role": "assistant",
"content": "안녕하세요! 이전 대화를 기억하고 있어요..."
},
"finish_reason": "stop",
"index": 0
}
],
"usage": {
"prompt_tokens": 1250,
"completion_tokens": 320,
"prompt_tokens_details": { "cached_tokens": 0 }
},
"costWon": 45,
"recalledMemories": [...],
"memorySaved": { "id": "turn-1756200000000", "keywords": [] },
"youtubeUsed": ["abc123def45"]
}
usage ไม่มี total_tokens — จะมี prompt_tokens, completion_tokens, prompt_tokens_details.cached_tokens และถ้าเป็นโมเดลให้เหตุผลจะมี completion_tokens_details.reasoning_tokens (รวมอยู่ใน completion_tokens แล้ว) memorySaved คืออ็อบเจกต์ข้อมูลเทิร์นที่เก็บ หรือ null (เกินเพดาน · เทิร์นที่เรียกเครื่องมือ) youtubeUsed คืออาร์เรย์ ID วิดีโอที่แทรกคำบรรยาย (ไม่ใช่ URL)
รูปแบบสตรีมมิง (SSE)
เมื่อ stream: true จะตอบกลับเป็นอีเวนต์ SSE ที่มีชื่อ ไม่ใช่รูปแบบ chunk ของ OpenAI ดังนั้นใช้ตัวแยกวิเคราะห์สตรีมของ OpenAI SDK อ่านไม่ได้ — ให้แยกวิเคราะห์ SSE เอง (การตอบกลับแบบไม่สตรีมเข้ากันได้กับ OpenAI)
| อีเวนต์ | data |
|---|---|
event: chunk |
RIDM: {"delta":"…"} (เมื่อเรียกเครื่องมือจะมีชิ้นส่วน tool_calls ด้วย) / ขายต่อ: อ็อบเจกต์ chunk จากต้นทางตามเดิม |
event: message_done |
RIDM: {finish_reason, usage, costWon, recalledMemories, memorySaved, memoryCapReached, emotion?, customProfile?, budgetExceeded?, tool_calls?} / ขายต่อ: {finish_reason, usage, costUsd, costWon, budgetExceeded?} ไม่มี id · choices · model |
event: error |
{message, code, status} — เนื่องจากเฮดเดอร์ (200) ถูกส่งไปแล้ว ให้ดูสถานะข้อผิดพลาดจริงจาก status |
data: [DONE] |
เครื่องหมายสิ้นสุดตามปกติ (บรรทัดสุดท้าย) |
event: chunk
data: {"delta":"안녕하세요"}
event: message_done
data: {"finish_reason":"stop","usage":{"prompt_tokens":1250,"completion_tokens":320,"prompt_tokens_details":{"cached_tokens":0}},"costWon":45,"recalledMemories":[],"memorySaved":{"id":"turn-1756200000000","keywords":[]}}
data: [DONE]
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไปแล้ว นี่คือรหัสที่ API นี้ส่งออกมา ข้อผิดพลาดที่เกิดหลังเริ่มตอบกลับใน stream: true จะมาเป็น event: error ({message, code, status}) โมเดลขายต่อก็ใช้ตารางเดียวกัน
| รหัส | HTTP | คำอธิบาย |
|---|---|---|
MODERATION_FLAGGED | 400 | ถูกบล็อกโดยการกลั่นกรองเนื้อหา (ridm: system+user, ขายต่อ: ข้อความ user) |
INSUFFICIENT_BALANCE | 402 | ยอดคงเหลือไม่พอ (จองขาออกทั้งหมดที่ขอไว้ล่วงหน้าเพื่อตรวจสอบ) |
MODEL_NOT_FOUND | 400 | โมเดลที่ไม่ได้ตั้งค่า |
INVALID_TOOLS / TOOLS_UNSUPPORTED_FOR_MODEL | 400 | ฟิลด์ที่เกี่ยวกับ tools ไม่สอดคล้องกัน / ขอเรียกเครื่องมือกับโมเดล Claude |
FILE_NOT_FOUND | 400 | fileIds มีไฟล์ที่ไม่มีอยู่ (หรือไฟล์ของพาร์ทเนอร์อื่น) |
FEATURE_DISABLED | 403 | ใช้ตัวเลือกนั้นในบัญชีที่ปิดฟีเจอร์ youtube · files · emotion |
RATE_LIMITED | HTTP 400, เนื้อหา status 429 | ต้นทางจำกัดความเร็ว หรือเกินเพดานการใช้จ่ายรายวันของการขายต่อ (ค่าเริ่มต้นต่อพาร์ทเนอร์ ₩100,000/วัน) |
UPSTREAM_TIMEOUT | HTTP 400, เนื้อหา status 504 | ต้นทางตอบกลับเกินเวลา (60 วินาที) |
UPSTREAM_INVALID_REQUEST | 400 | โมเดลต้นทางปฏิเสธคำขอ (ต้นทาง 400 · 422) |
INVALID_RESPONSE_FORMAT | 400 | ใช้ response_format: json_object แต่ในข้อความไม่มีคำว่า "json" (ตระกูล OpenAI) |
REPORT_ONLY_MODEL | 400 | ระบุ ridm/saju-report — ใช้ได้เฉพาะ API รายงานซาจู |
| (ไม่มี) | 400 | ไม่มี user ในโมเดล ridm/* · systemPrompt เกิน 8,000 ตัวอักษร · คำนำหน้าโมเดลที่ไม่รองรับ |
provider_not_configured | 503 | ตอนนี้โมเดล Claude ไม่ได้เชื่อมต่ออยู่ |
ข้อควรระวัง
- การแทรกคำบรรยาย YouTube: เมื่อ youtube:true จะดึงคำบรรยายจากลิงก์ YouTube ในข้อความสุดท้ายแล้วรวมเข้าในโทเค็นขาเข้า หากดึงคำบรรยายไม่ได้ การสนทนาจะดำเนินต่อโดยไม่แทรก และ
youtubeUsedในการตอบกลับจะเป็นอาร์เรย์ว่าง (เฉพาะ API สรุป YouTube แบบเดี่ยวที่ได้ 400 และไม่คิดค่าบริการ) - เข้ากันได้กับโมเดลต้นฉบับ: หากระบุค่า model เป็น openai/* หรือ google/*, anthropic/* จะเรียกโมเดลต้นฉบับตามเดิมโดยไม่มีฟีเจอร์หน่วยความจำ (ต้นทุน × อัตราแลกเปลี่ยน × 1.10)
- ส่วนลดแคชพรอมต์: โมเดลตระกูล OpenAI (openai/*, ridm/gpt-*) หากส่งส่วนต้นที่เหมือนกัน (1,024 โทเค็นขึ้นไป) ซ้ำ โทเค็นขาเข้าที่ตรงกับแคชต้นทางจะคิดค่าบริการที่ 30% ของราคาขาเข้า ตรวจสอบได้จาก
usage.prompt_tokens_details.cached_tokensในการตอบกลับ และcachedTokensของGET /usage/logsการตรงแคชหรือไม่อาจต่างกันในแต่ละการเรียกตามนโยบายของต้นทาง โมเดล Google ไม่มีแคชจึงใช้ราคาขาเข้าเต็ม โมเดล Claude ก็ไม่ได้ขอแคช จึงใช้ราคาขาเข้าเต็มเช่นกัน - ยกเว้น REPORT_ONLY_MODEL: ridm/saju-report เป็นแบบครั้งเดียวที่ไม่มีหน่วยความจำ จึงใช้ที่เอนด์พอยต์นี้ไม่ได้ (400)
Custom Profile (โปรไฟล์กำหนดเอง)
เฉพาะโมเดล ridm/* เก็บและจัดการชื่อฟิลด์-ค่าที่กำหนดเองแยกตามผู้ใช้ปลายทาง สามารถเก็บค่าฟิลด์ที่ดึงออกมาอัตโนมัติ ให้พาร์ทเนอร์กำหนดค่าเอง หรือใส่ฟิลด์ที่ต้องการลงในพรอมต์ของเทิร์นนี้ได้ ค่าจะสะสมไปเรื่อยๆ และแม้สคีมาจะเปลี่ยน ค่าเดิมก็ยังคงอยู่ (soft-update)
พารามิเตอร์คำขอ (POST /api/v1/partners/v1/chat/completions)
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
extractProfileFields |
string[] | อาร์เรย์ชื่อฟิลด์ที่จะดึงอัตโนมัติจากบทสนทนา (สูงสุด 100 รายการ) ในรอบการสรุป LLM จะจัดลักษณะ · ความชอบ · สถานการณ์ของผู้ใช้ตามชื่อฟิลด์เหล่านี้แล้วเก็บไว้ หากค่าที่ดึงได้ว่างหรือเป็น null จะข้ามและคงค่าเดิมไว้ (แบบสะสม ค่าที่กำหนดเองจะไม่ถูกค่าที่ดึงได้เขียนทับ) ไม่มีค่าบริการเพิ่ม |
injectProfileFields |
string[] | อาร์เรย์ชื่อฟิลด์ที่จะใส่ในพรอมต์ของเทิร์นนี้ จะแทรกเฉพาะฟิลด์ที่ระบุลงในพรอมต์ ไม่มีการแทรกอัตโนมัติ ฟิลด์ที่ถูกแทรกจะคิดค่าบริการเป็นโทเค็นขาเข้าทุกเทิร์น เลือกเฉพาะฟิลด์ที่จำเป็น |
endUserProfile |
object | อ็อบเจกต์ชื่อฟิลด์-ค่า ตัวอย่าง: { "name": "Jane Kim", "age": "35", "interest": "parenting" } ค่าที่ระบุจะเขียนทับค่าที่ดึงได้ สูงสุด 100 ฟิลด์ ค่าละ 150 ตัวอักษรโดยค่าเริ่มต้น (สูงสุด 500 ตัวอักษร) |
profileValueMaxChars |
number | จำนวนตัวอักษรสูงสุดของค่า (ค่าเริ่มต้น 150 สูงสุด 500 — ค่าที่เกินจะปรับเป็น 500) ใช้เฉพาะกับค่าที่เก็บในคำขอนั้น (endUserProfile · ค่าที่ดึงได้ในรอบสรุปนี้) และไม่ถูกบันทึก จึงต้องส่งใหม่ทุกคำขอ |
ตัวอย่างคำขอ (RIDM chat)
{
"model": "ridm/gpt-5.6-terra",
"user": "enduser_123",
"messages": [
{ "role": "user", "content": "Help me plan my kid's birthday party tomorrow" }
],
"extractProfileFields": ["childAge", "interests", "budget", "constraints"],
"injectProfileFields": ["name", "childAge", "interests"],
"endUserProfile": {
"name": "Jane Kim",
"childAge": "7",
"interests": "science, art"
},
"profileValueMaxChars": 200
}
โปรไฟล์ในการตอบกลับ
การตอบกลับของคำขอที่ส่งพารามิเตอร์โปรไฟล์ (สำหรับสตรีมมิงคือ message_done) จะมีฟิลด์ customProfile แนบมา
"customProfile": {
"injected": ["name", "childAge", "interests"], // fields injected into this turn's prompt
"stored": 4, // number of fields currently stored
"extractPending": ["budget"] // extraction targets that have no value yet
}
API ลบ
หากต้องการลบฟิลด์ที่ระบุ ให้ส่งคำขอ DELETE:
DELETE /api/v1/partners/v1/profile/{endUserId}/field/{key}
X-Partner-Api-Key: your-api-key
การตอบกลับ: { "success": true, "data": { "deleted": true } } — แม้เป็นคีย์ที่ไม่มีอยู่หรือ endUserId ที่ไม่เคยเห็นมาก่อน ก็จะได้ 200 พร้อม "deleted": false (ไม่สร้างผู้ใช้ปลายทางใหม่) API นี้ไม่มีรหัสข้อผิดพลาดเฉพาะ — มีเพียงข้อผิดพลาดทั่วไป
เพดานและข้อจำกัด
- เพดานฟิลด์: สูงสุด 100 ฟิลด์ต่อผู้ใช้ปลายทาง หากเกินจะลบฟิลด์ที่เก่าที่สุดก่อน
- ความยาวค่า: ค่าเริ่มต้น 150 ตัวอักษรต่อฟิลด์ สูงสุด 500 ตัวอักษร ปรับได้ด้วย profileValueMaxChars
- การเก็บแบบสะสม: ค่าที่ดึงด้วย extractProfileFields จะสะสม ค่าที่ว่างหรือเป็น null จะข้ามและคงค่าเดิมไว้ การลบฟิลด์ทำได้เฉพาะผ่าน DELETE API ด้านบน (หรือการลบอัตโนมัติตามลำดับเก่าสุดเมื่อเกิน 100 รายการ) ค่าที่ระบุด้วย endUserProfile จะเขียนทับค่าที่ดึงได้
- เกณฑ์ความยาวค่าเป็นรายคำขอ: profileValueMaxChars ไม่ถูกบันทึก และใช้เฉพาะกับค่าที่เก็บในคำขอนั้น
- Soft Update: แม้สคีมา (ชื่อฟิลด์) จะเปลี่ยน ค่าเดิมก็ยังคงอยู่ และจะรวมกับค่าใหม่ทุกครั้งที่เรียก
- เฉพาะ ridm/*: การขายต่อ (openai/*, google/*) จะละเว้นโปรไฟล์
LLM API (ขายต่อ)
ขายต่อโมเดล LLM ต้นฉบับ เช่น openai/*, google/* (ไม่มีหน่วยความจำ ตอบกลับตามต้นฉบับ) ในคำขอของโมเดลขายต่อ user, systemPrompt, recallCount, memoryCap, summaryEvery, emotion, candor จะถูกละเว้น (คำสั่งระบบให้ใส่เป็น {"role":"system"} ใน messages) และการตอบกลับจะไม่มีฟิลด์หน่วยความจำ (recalledMemories ฯลฯ) ราคา = ต้นทุน × อัตราแลกเปลี่ยน × 1.10
โมเดลที่ให้บริการ (รายการเดียวกับ GET /api/v1/partners/v1/models)
- OpenAI (23 รุ่น):
openai/gpt-6-astra·openai/gpt-6-sol·openai/gpt-6-luna·openai/gpt-5.6-sol·openai/gpt-5.6-terra·openai/gpt-5.6-luna·openai/gpt-5.5·openai/gpt-5.4·openai/gpt-5.4-mini·openai/gpt-5.4-nano·openai/gpt-5.2·openai/gpt-5.1·openai/gpt-5·openai/gpt-5-mini·openai/gpt-5-nano·openai/gpt-4.1·openai/gpt-4.1-mini·openai/gpt-4.1-nano·openai/gpt-4o·openai/gpt-4o-mini·openai/o3·openai/o3-mini·openai/o4-mini - Google (3 รุ่น):
google/gemini-3.5-flash·google/gemini-3.5-flash-lite·google/gemini-3.1-pro - Anthropic (13 รุ่น): ดูหัวข้อโมเดล Claude ด้านล่าง
- RIDM: มีโมเดลแบบจดจำที่ใส่คำนำหน้า
ridm/ให้ชื่อเดียวกับแต่ละโมเดลข้างต้น (ราคาขายต่อ × 1.3) และridm/saju-reportสำหรับรายงานซาจูโดยเฉพาะ (เรียกได้ทาง/reading/reportเท่านั้น)
curl https://api.hrum.ai/api/v1/partners/v1/models \
-H "X-Partner-Api-Key: your-api-key"
การตอบกลับของ GET /api/v1/partners/v1/models — ไม่ใช่รูปแบบ models.list ของ OpenAI ราคาเป็นวอน (₩) ต่อ 1M โทเค็น และตัวเลขด้านล่างเป็นตัวอย่าง โมเดล Claude จะแสดงในรายการเฉพาะเมื่อตั้งค่าไว้ในเซิร์ฟเวอร์
{
"success": true,
"data": {
"models": [
{ "modelId": "openai/gpt-5.6-terra", "upstream": "gpt-5.6-terra", "provider": "openai", "input_cost_krw": 1234, "output_cost_krw": 9876, "category": "base" },
{ "modelId": "ridm/gpt-5.6-terra", "upstream": "gpt-5.6-terra", "provider": "openai", "input_cost_krw": 1604.2, "output_cost_krw": 12838.8, "category": "ridm" }
]
}
}
API นี้ไม่มีรหัสข้อผิดพลาดเฉพาะ — มีเพียงข้อผิดพลาดทั่วไป ใช้ได้ฟรี
โมเดล Claude (anthropic/*, ridm/claude-*)
- โมเดล (13 รุ่น):
anthropic/claude-fable-5-1·anthropic/claude-opus-5-5·anthropic/claude-sonnet-5-5·anthropic/claude-haiku-5-5·anthropic/claude-fable-5·anthropic/claude-opus-5·anthropic/claude-sonnet-5·anthropic/claude-opus-4-8·anthropic/claude-opus-4-7·anthropic/claude-opus-4-6·anthropic/claude-opus-4-5·anthropic/claude-sonnet-4-6·anthropic/claude-haiku-4-5(ขายต่อ) / ใส่คำนำหน้าridm/ให้ชื่อเดียวกันจะเป็น RIDM Memory API (ราคาขายต่อ × 1.3) - รูปแบบคำขอเหมือนเดิม: ส่งในรูปแบบ OpenAI แล้วเซิร์ฟเวอร์จะแปลงเป็นรูปแบบ Claude ก่อนเรียก แม้มีข้อความ system หลายข้อความก็จะรวมเป็นข้อความเดียวแล้วส่งต่อ
- ละเว้น temperature · top_p: Claude 5.x ไม่รับค่าการสุ่ม ส่งไปก็ไม่มีผล (ไม่มีข้อผิดพลาด) ปรับโทนการตอบด้วยพรอมต์ system
- max_tokens: หากละไว้จะเป็น 8,192 Claude Fable 5 · 5.1, Opus 5 · 5.5 เปิดการให้เหตุผลภายในไว้เสมอ โทเค็นการให้เหตุผลจึงคิดค่าบริการเป็นโทเค็นขาออกด้วย และเพื่อไม่ให้คำตอบถูกตัด เซิร์ฟเวอร์จะเพิ่มเผื่อ 1,500 โทเค็นให้ max_tokens ที่ขอแล้วเรียก
- ช่วงข้อความยาวของ Haiku 5.5: หากขาเข้าของคำขอเดียวเกิน 100,000 โทเค็น ราคาทางการของ Anthropic จะอยู่ในช่วง ×5 คำขอนั้นจึงคิดค่าบริการโทเค็นขาเข้า · ขาออก ×5
- ขอบเขตที่รองรับ: การสนทนาด้วยข้อความ (รวมสตรีมมิง) โมเดล Claude ไม่รองรับการเรียกเครื่องมือ (
tools·tool_choice·parallel_tool_calls) จึงคืน 400TOOLS_UNSUPPORTED_FOR_MODEL— โมเดลขายต่อของ OpenAI · Google รองรับการเรียกเครื่องมือ ไม่รองรับอินพุตรูปภาพ
โมเดลคิด (ให้เหตุผล) กับ max_tokens: โมเดลที่ใช้การคิดแบบซ่อน (thinking/reasoning) จะนับโทเค็นการคิดรวมในเพดานขาออก เซิร์ฟเวอร์เพิ่มส่วนเผื่อให้แล้ว แต่ถ้า max_tokens เล็กมาก (เช่น 16) เนื้อหาอาจว่างและตอบกลับด้วย finish_reason: "length" และโทเค็นที่ต้นทางใช้ไปจะถูกคิดค่าบริการ ค่าขั้นต่ำที่แนะนำคือ 64 ขึ้นไป โมเดลที่เกี่ยวข้อง: openai/gpt-5 · openai/gpt-5-mini · openai/gpt-5-nano · openai/gpt-6-astra · openai/o3 · openai/o3-mini · openai/o4-mini · anthropic/claude-opus-5 · anthropic/claude-opus-5-5 · anthropic/claude-fable-5 · anthropic/claude-fable-5-1 · google/gemini-3.1-pro (รวมโมเดลชื่อเดียวกันที่มีคำนำหน้า ridm/)
ส่วนเผื่อสำหรับการคิดกับโทเค็นที่ถูกเรียกเก็บ: โมเดลที่ปิดการคิดไม่ได้ (openai/gpt-5 · openai/gpt-5-mini · openai/gpt-5-nano · openai/gpt-6-astra · openai/o3 · openai/o3-mini · openai/o4-mini · google/gemini-3.1-pro) และโมเดลที่เปิด thinking ไว้เสมอ (anthropic/claude-opus-5 · anthropic/claude-opus-5-5 · anthropic/claude-fable-5 · anthropic/claude-fable-5-1) (รวมโมเดลชื่อเดียวกันที่มีคำนำหน้า ridm/) เซิร์ฟเวอร์จะเพิ่มส่วนเผื่อสำหรับการคิด (สูงสุด 1,500 โทเค็น) บน max_tokens ที่ขอเพื่อรับประกันว่าจะได้คำตอบ โทเค็นการคิดถูกเรียกเก็บในราคาขาออกด้วย โทเค็นขาออกที่ถูกเรียกเก็บจริงจึงอาจมากกว่า max_tokens (ตัวอย่าง: คำขอ max_tokens 200 ถูกเรียกเก็บ การคิด 747 + เนื้อหา 81 = 828 โทเค็น) หากต้องคุมเพดานค่าใช้จ่ายอย่างเข้มงวด ให้ใช้โมเดลที่ปิดการคิดได้ เช่น google/gemini-3.5-flash
POST /api/v1/partners/v1/chat/completions
พารามิเตอร์คำขอ (ไม่มีเลเยอร์หน่วยความจำ)
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
model |
string | O | ridm/gpt-5.6-terra (จดจำ) · ขายต่อคือ openai/gpt-5.2, google/gemini-3.5-flash ฯลฯ — รายการทั้งหมดดูที่ ราคา |
messages |
array | O | ข้อความรูปแบบ OpenAI |
temperature |
number | 0.0~2.0 (หากละไว้ใช้ค่าเริ่มต้นของโมเดล) top_p (0~1), presence_penalty · frequency_penalty (-2~2), seed, stop, response_format, tools · tool_choice · parallel_tool_calls ก็รับในช่วงเดียวกับ RIDM (Claude เรียกเครื่องมือไม่ได้) |
|
systemPrompt |
string | ถูกละเว้น — โมเดลขายต่อจะละเว้น systemPrompt จึงให้ใส่เป็น {"role":"system"} ใน messages |
|
fileIds |
string[] | ID เอกสารที่จะแทรก (UUID สูงสุด 5 รายการ แทรกเฉพาะที่ระบุ) | |
max_tokens |
number | โทเค็นขาออกสูงสุด (1~8,192 เกินจะได้ 400) โมเดลคิด (ให้เหตุผล) นับโทเค็นการคิดรวมในเพดานนี้ หากเล็กเกินไป (เช่น 16) เนื้อหาอาจว่างและได้ finish_reason: "length" และโทเค็นที่ต้นทางใช้ไปจะถูกคิดค่าบริการ แนะนำขั้นต่ำ 64 ขึ้นไป |
|
emotion |
boolean | ถูกละเว้น (บัญชีที่ปิดฟีเจอร์อารมณ์ หากส่ง emotion:true จะได้ 403 FEATURE_DISABLED) |
|
summaryEvery |
number | ถูกละเว้น |
ตัวอย่างการใช้งาน (เข้ากันได้กับ OpenAI SDK)
const client = new OpenAI({
apiKey: 'your-float-api-key',
baseURL: 'https://api.hrum.ai/api/v1/partners/v1',
defaultHeaders: { 'X-Partner-Api-Key': 'your-float-api-key' }
});
const response = await client.chat.completions.create({
model: 'openai/gpt-5.6-terra',
messages: [{ role: 'user', content: 'Hello' }]
});
// RIDM model example: model: 'ridm/gpt-5.6-terra'
การตอบกลับ
การตอบกลับแบบไม่สตรีมใช้สคีมาที่เข้ากันได้กับ OpenAI และเพิ่ม costUsd · costWon · requestId ส่วน stream: true ไม่ใช่รูปแบบ chunk ของ OpenAI จึงอ่านด้วยตัวแยกวิเคราะห์สตรีมของ OpenAI SDK ไม่ได้ — ให้ดูรูปแบบสตรีมมิง (SSE) แล้วแยกวิเคราะห์เอง
{
"id": "chatcmpl-1791452814000",
"object": "chat.completion",
"created": 1791452814,
"model": "openai/gpt-5.6-terra",
"usage": { "prompt_tokens": 9, "completion_tokens": 12, "prompt_tokens_details": { "cached_tokens": 0 } },
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "Hello! How can I help?" }, "finish_reason": "stop" }
],
"costUsd": 0.000162,
"costWon": 1,
"requestId": "resale-..."
}
รหัสข้อผิดพลาดเหมือนกับตารางข้อผิดพลาดของ RIDM Memory API โมเดลขายต่อจะมีเพดานการใช้จ่ายรายวัน (RATE_LIMITED) ด้วย
API AI อ่านดวงซาจู
AI แบบสร้างสรรค์ (Generative AI) วิเคราะห์ซาจูและให้การตีความดวงพร้อมคำแนะนำเฉพาะบุคคล คิดค่าบริการตามโทเค็น และคืนเฉพาะผลการตีความ
POST /api/v1/partners/v1/reading
สร้างการอ่านดวงซาจูด้วย AI จากซาจู พรอมต์และทฤษฎีภายในไม่เปิดเผย
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
speed |
string | fast (ค่าเริ่มต้น ตอบเร็ว) | value (ตอบช้า ลดราคา 20%) |
|
birth |
object | birth หรือ saju อย่างใดอย่างหนึ่ง | {year, month, day, hour?, minute?, gender, calendar?} calendar: solar (ค่าเริ่มต้น) | lunar — ปฏิทินจันทรคติจะแปลงเป็นสุริยคติแล้วคำนวณ สถานที่เกิด · เขตเวลา · เดือนอธิกมาส (2026-10-17): รับฟิลด์ไม่บังคับ isLeapMonth · timezone · birthLatitude · birthLongitude · country · zaSiRule · birthTimePrecision ด้วยชื่อเดียวกันและกฎเดียวกับ API ปฏิทินหมื่นปี ข้อมูลการเกิดเดียวกันจึงได้สี่เสาเหมือนปฏิทินหมื่นปี พิกัดต้องส่งทั้งสองค่า หากส่งค่าเดียวจะได้ 400 INVALID_LOCATION หากไม่ส่งเลยจะคำนวณเหมือนเดิมทุกอย่าง (เวลาเกิดเป็นเวลาเกาหลี ปฏิทินจันทรคติเป็นเดือนปกติ) ส่วนโหราศาสตร์ตะวันตกจะวาดผังจากเวลาที่ใช้จริงใน timezone ณ เวลาเกิดนั้น (รวมเวลาออมแสง) และพิกัด หากไม่รู้จัก birth.timezone การตอบกลับจะมี warnings (field: "birth.timezone") แนบมา |
saju |
object | birth หรือ saju อย่างใดอย่างหนึ่ง | ป้อนสี่เสาโดยตรง {"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}} หากส่งพร้อม birth จะตรวจสอบไขว้แล้วยึด saju ก่อน (sajuMismatch) |
year / month / day / gender |
number / string | ฟิลด์แบบแบน (แบบเก่า) จะถือเป็น birth (สุริยคติ) เฉพาะเมื่อมีค่าครบทั้งสี่ หากไม่มีทั้ง birth · saju · ฟิลด์แบบแบน จะได้ 400 MISSING_SUBJECT_INPUT |
|
hour / minute |
number | ชั่วโมงเกิด 0-23 / นาที 0-59 (ไม่บังคับ) หากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน | |
question |
string | O | คำถามเกี่ยวกับการอ่านดวง (เช่น "เส้นทางชีวิตของฉันเป็นอย่างไร?") |
tone |
string | โทนการตอบ ("formal", "casual", "warm" ค่าเริ่มต้น: "warm") | |
candor |
string | โทนคำพูด — ระดับความตรงไปตรงมาของคำตอบ t / f (ค่าเริ่มต้น) ไม่คิดค่าบริการ ดู โทนคำพูด (ชื่อชั่วคราว) |
|
persona |
string | ตัวละครที่แอปเลือก (ชื่อ · สำนวน · ท่าที สูงสุด 2,000 ตัวอักษร) ใช้กับสำนวนเท่านั้น และไม่มีลำดับความสำคัญเหนือการตีความซาจู · ขอบเขตความปลอดภัย · คำสั่งเรื่องความยาว คิดค่าบริการเป็นอินพุตเหมือนคำถาม (จำนวนตัวอักษร × 0.25) หากมีหลายตัวละคร ให้เลือกจากรายการที่อนุญาตบนเซิร์ฟเวอร์แล้วส่ง — อย่าใส่ข้อความที่เบราว์เซอร์ส่งมาโดยตรง | |
maxLength |
number | ความยาวการตอบสูงสุด (100~2,000 ค่าเริ่มต้น: 800) | |
tools |
object | แฟล็กฟีเจอร์เพิ่มเติม ตัวอย่าง: {"astrology": true, "youtube": true} คีย์ที่ไม่รู้จักจะได้ 400 UNKNOWN_TOOL |
|
dream |
string | เนื้อหาความฝันที่ผู้ใช้ปลายทางเล่า (1~1,000 ตัวอักษร) หากส่งมา การทำนายฝันจะรวมอยู่ในการอ่านดวงอัตโนมัติ ดูรายการที่รวมอยู่ | |
exclude |
string[] | สิ่งที่จะตัดออกจากรายการที่รวมอยู่ ziwei (จื่อเวยโต่วซู่) · astro (โหราศาสตร์ตะวันตก) · dream (ทำนายฝัน) · tarot (ไพ่ทาโรต์) รายการที่ตัดออกจะไม่มีทั้งหลักฐานอ้างอิงและค่าบริการ ตัวอย่าง: ["ziwei", "astro"] ค่าเดิม today ยังรับได้แต่ไม่มีผลใดๆ (ดวงวันนี้ไม่ใช่รายการที่รวมอยู่อีกต่อไป) |
|
tarot |
object | หากส่งมา จะสุ่มไพ่ทาโรต์สำหรับการอ่านดวงนี้แล้วอ่านไปด้วยกัน ตัวเลือกเดียวกับ API ไพ่ทาโรต์: count (1~10) หรือ spread อย่างใดอย่างหนึ่ง, reversed, seed ภาษาของไพ่จะตามภาษาของคำถาม ไพ่ที่สุ่มได้ (รวมที่อยู่รูปภาพ) จะอยู่ใน tarot ของการตอบกลับ |
|
only |
string | เรียก AI เพียงตัวเดียวภายใน AI ซาจูแยกต่างหาก saju · ziwei · astro · tarot · dream หากส่งพร้อม exclude จะได้ 400 ดู เรียก AI ตัวเดียวแยก |
พารามิเตอร์คำขอ — ตัวเลือก tools
| ตัวเลือก | ชนิด | คำอธิบาย |
|---|---|---|
astrology |
boolean | เมื่อเป็น true จะนำผังดวงกำเนิด (Natal Chart) ของโหราศาสตร์ตะวันตกมาใช้ในการอ่านดวง ไม่มีค่าบริการแยก |
youtube |
boolean | เมื่อเป็น true จะแทรกคำบรรยายของลิงก์ YouTube ใน question (คิดค่าบริการเป็นอินพุตตามจำนวนตัวอักษรคำบรรยาย × 0.25) ไม่ใช้ฟิลด์ youtube ระดับบนสุด — ต้องอยู่ใน tools เท่านั้น |
fileIds |
string[] | ID เอกสารที่จะแทรก (UUID สูงสุด 5 รายการ) |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/reading \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"question": "Is this a good year to change jobs?",
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female" },
"maxLength": 600,
"tone": "warm"
}'
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"interpretation": "당신의 사주에서 보이는 특징은...",
"sajuSource": "computed",
"usage": {
"inputTokens": 450,
"outputTokens": 280
},
"costPoints": 18
}
}
ฟิลด์ในการตอบกลับ
| ฟิลด์ | คำอธิบาย |
|---|---|
interpretation | ข้อความการตีความ |
sajuSource | computed (คำนวณจาก birth) | provided (ใช้ saju ที่ป้อน) |
sajuMismatch | คำเตือนเมื่อส่ง birth และ saju มาพร้อมกันแต่เสาไม่ตรงกัน ({pillars, computed, note}) กรณีอื่นเป็น null/ไม่มี |
toolsUsed | เครื่องมือที่ทำงานจริง (เช่น ["youtube"]) |
toolsSkipped | เครื่องมือที่ขอแต่ถูกข้าม [{tool, reason}], reason: unavailable | cap_exceeded | error | auto_rejected |
filesUsed | ID เอกสารที่ถูกแทรก (เมื่อใช้ tools.fileIds) |
usage | จำนวนโทเค็นเพื่ออ้างอิง (inputTokens เป็นค่าจริงที่รวมซาจู · พรอมต์ระบบ — ไม่ใช่เกณฑ์คิดค่าบริการ) |
costPoints | ยอดที่หักจริง (₩) |
modulesUsed | รายการที่รวมอยู่จริง (เช่น ["saju","ziwei","astro"] โดย saju อยู่หน้าสุด) จะแนบมาเฉพาะเมื่อเปิดฟีเจอร์รายการที่รวมอยู่ |
moduleFees | ค่าบริการคงที่ต่อรายการที่รวมอยู่ (₩) (เช่น {"ziwei":50,"astro":20}) รวมอยู่ใน costPoints แล้ว จะแนบมาเฉพาะเมื่อเปิดฟีเจอร์รายการที่รวมอยู่ |
tarot | ไพ่ที่สุ่มได้เมื่อรวมไพ่ทาโรต์ — รูปแบบเดียวกับการตอบกลับของ API ไพ่ทาโรต์ (รวม imageUrl ของ cards[] ไม่รวม question · costPoints) |
only | คืนค่า only ของคำขอตามเดิม (เฉพาะเมื่อส่งมา) หาก only ไม่ใช่ saju จะไม่ใช้ซาจู จึงไม่มี sajuSource |
support | ข้อมูลสายด่วนช่วยเหลือในภาวะวิกฤต {message, contacts:[{name, number, hours}]} หากเนื้อหา dream เป็นการแสดงออกถึงภาวะวิกฤต จะไม่เรียก AI แต่ใส่ข้อมูลความช่วยเหลือใน interpretation แล้วคืนด้วย costPoints: 0 จะแนบมาด้วยในกรณีที่ตรวจความปลอดภัยไม่ได้ |
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไปแล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส |
|---|---|
| 400 | MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE · UNKNOWN_TOOL · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUND · INVALID_TOOL_MODE · MEMORY_REQUIRES_MEMORY_ENDPOINT · EMOTION_REQUIRES_MEMORY · MISSING_ENDUSER_ID (หน่วยความจำ) · ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALID (เรียก AI ตัวเดียวแยก) |
| 402 | INSUFFICIENT_BALANCE — ก่อนเรียกจะจองค่าขาออก maxLength × 2 โทเค็น (ระดับ value หรือคำถามที่ไม่ใช่ภาษาเกาหลี +4,000) ไว้ล่วงหน้า จึงอาจถูกปฏิเสธได้แม้ยอดเรียกเก็บจริงจะน้อยกว่า |
| 403 | FEATURE_DISABLED — ใช้ฟีเจอร์ที่ปิดในบัญชี (youtube · files · emotion) |
รายการที่รวมอยู่ — จื่อเวยโต่วซู่ · โหราศาสตร์ตะวันตก · ทำนายฝัน · ไพ่ทาโรต์
ใน AI ซาจูมี AI ซาจู · จื่อเวยโต่วซู่ · โหราศาสตร์ตะวันตก · ไพ่ทาโรต์ · ทำนายฝันอยู่ครบ เสาประจำวันจะสะท้อนในทุกการอ่านดวงโดยพื้นฐานแม้ไม่เรียกแยก (ไม่มีค่าบริการเพิ่ม) เมื่อเรียกแบบรวมครั้งเดียว จะอ่านดวงร่วมกันโดยใช้ผลคำนวณของรายการที่รวมอยู่เป็นหลักฐาน และรายการที่ไม่ต้องการให้ตัดออกด้วย exclude หากต้องการเรียก AI เพียงตัวเดียว ให้ใช้ only หากต้องการแค่ผลคำนวณ ก็เรียกรายการเดียวกันแยกทีละตัวทางเอนด์พอยต์แบบคำนวณ (/ziwei-chart · /astrology (โหราศาสตร์ตะวันตกแบบครบชุด) · /dream · /tarot) เพื่อสร้างแอปเองได้ ใน /reading/memory ก็ใช้ฟิลด์เดียวกัน
| รายการ | รวมเมื่อใด | สิ่งที่ใส่เป็นหลักฐาน | ค่าบริการ (= ราคา 1 ครั้งของเอนด์พอยต์เดี่ยว) |
|---|---|---|---|
จื่อเวยโต่วซู่ ziwei | รวมโดยพื้นฐานเมื่อมีวันเดือนปีเกิด + เวลาเกิด (hour) | สรุปผังดวง — วังชะตา · วังกาย · สามทิศสี่ตรง, สี่การแปรของปีเกิด, ช่วงใหญ่ 10 ปี · ปีจรปัจจุบัน | /ziwei-chart |
โหราศาสตร์ตะวันตก astro | รวมโดยพื้นฐานเมื่อมีวันเดือนปีเกิด (ไม่มีเวลาก็ได้) | สรุปผังดวงกำเนิด — ราศีและองศาของดวงอาทิตย์ · ดวงจันทร์ · ดาวพุธ~ดาวเสาร์, ลัคนา (เมื่อทำได้) | ₩20 (สินค้าโหราศาสตร์ตะวันตกแบบเดี่ยวคือ /astrology) |
ทำนายฝัน dream | เมื่อส่งเนื้อหาความฝันมาใน dream | เนื้อหาความฝัน + คำสัญลักษณ์ที่พบในความฝัน | /dream (ถ้าไม่มีตัวเลือกจะเป็น 0 วอน) |
ไพ่ทาโรต์ tarot | เมื่อส่ง tarot มา | ไพ่ที่สุ่มได้ในคำขอนี้และความหมายแบบหัวตั้ง · หัวกลับ (อยู่ใน tarot ของการตอบกลับพร้อมที่อยู่รูปภาพ) | /tarot |
- การคิดค่าบริการ: นำราคาโทเค็นเดิม (โทเค็นขาเข้าเท่ากับจำนวนตัวอักษรของคำถาม + persona + บล็อกหลักฐานของรายการที่รวม × 0.25 และโทเค็นขาออก) มาบวกราคา 1 ครั้งของเอนด์พอยต์เดี่ยวของแต่ละรายการที่รวมอยู่ บล็อกหลักฐานเป็นสรุปไม่เกิน 1,500 ตัวอักษรต่อรายการ รายการที่ฟีเจอร์ถูกปิดในบัญชีหรือไม่มีราคาจะไม่ถูกรวม ค่าบริการแต่ละรายการและช่วงราคาโดยประมาณต่อ 1 ครั้งอยู่ที่ ราคา
- คำขอที่ส่งเฉพาะสี่เสา (
saju) ไม่มีวันเดือนปีเกิด จึงไม่รวมจื่อเวยโต่วซู่ · โหราศาสตร์ตะวันตก (ทำนายฝัน · ไพ่ทาโรต์ยังรวมอยู่) - ความสัมพันธ์กับ
tools.astrology: หากรวมรายการโหราศาสตร์ตะวันตก จะข้ามการแทรกผังของtools.astrologyเพื่อไม่ให้ใส่ผังดวงกำเนิดเดียวกันซ้ำสองครั้ง หากรายการโหราศาสตร์ตะวันตกถูกตัดออก (excludeหรือฟีเจอร์ปิด)tools.astrologyจะทำงานเหมือนตอนนี้ - ระบบความปลอดภัยของการทำนายฝัน: หากเนื้อหา
dreamเป็นการแสดงออกถึงภาวะวิกฤต จะไม่เรียก AI แต่คืนข้อมูลความช่วยเหลือ (support) ด้วยcostPoints: 0 - สวิตช์ฟีเจอร์: ตอนนี้เปิดอยู่ หากปิดการตั้งค่าเซิร์ฟเวอร์ แม้ส่ง
exclude·dream·tarotก็จะถูกละเว้น และการอ่านดวง · ราคา · การตอบกลับจะเหมือนสมัยที่ยังไม่มีรายการที่รวมอยู่ (ไม่มีmodulesUsed·moduleFees·tarot)
ตัวอย่างคำขอ (POST /api/v1/partners/v1/reading)
{
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
"question": "I can't stop thinking about last night's dream. What could it mean for me right now?",
"dream": "큰 뱀이 집 안으로 들어와 내 발 옆에 똬리를 틀었어요",
"tarot": { "spread": "past-present-future" }
}
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"interpretation": "뱀이 집 안으로 들어와 곁에 머무는 꿈은...",
"sajuSource": "computed",
"modulesUsed": ["saju", "dream", "ziwei", "astro", "tarot"],
"moduleFees": { "dream": 30, "ziwei": 50, "astro": 20, "tarot": 20 },
"tarot": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": null,
"cards": [
{ "position": 1, "positionLabel": "과거", "id": "wands_10", "name": "완드의 10", "nameEn": "Ten of Wands", "arcana": "wands", "reversed": true, "keywords": ["내려놓기", "위임", "해방"], "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.", "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp" }
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp"
},
"usage": {
"inputTokens": 3140,
"outputTokens": 760
},
"costPoints": 162
}
}
เฉพาะซาจู (ตัดรายการอื่นออกทั้งหมด) (POST /api/v1/partners/v1/reading)
{
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
"question": "Is this a good year to change jobs?",
"exclude": ["ziwei", "astro"]
}
เรียก AI ตัวเดียวแยก — only
ใน AI ซาจูมี AI ซาจู · จื่อเวยโต่วซู่ · โหราศาสตร์ตะวันตก · ไพ่ทาโรต์ · ทำนายฝันอยู่ครบ แทนที่จะเรียกแบบรวมครั้งเดียวเหมือนข้างบน ก็เรียก AI ที่ต้องการเพียงตัวเดียวแยกด้วย only ได้ AI ตัวนั้นจะตอบโดยดูเฉพาะหลักฐานของตัวเอง (ผังดวง · ผัง · ไพ่ที่สุ่มได้ · ตัวเลือกการทำนายฝัน) และไม่ใส่รายการอื่น
only | เรียกอะไร | อินพุตที่ต้องใช้ | ค่าบริการ |
|---|---|---|---|
saju | AI ซาจู (เฉพาะซาจู ไม่มีรายการอื่น) | birth หรือ saju | ราคาโทเค็นเท่านั้น (ไม่มีค่าบริการคงที่) |
ziwei | AI จื่อเวยโต่วซู่ | birth + เวลาเกิด (hour) | ราคาโทเค็น + ราคา 1 ครั้งของ /ziwei-chart |
astro | AI โหราศาสตร์ตะวันตก | birth (ไม่มีเวลาก็ได้) | ราคาโทเค็น + ₩20 (ค่าบริการคงที่ของรายการโหราศาสตร์ตะวันตก) |
tarot | AI ไพ่ทาโรต์ | ตัวเลือก tarot — ไม่ต้องใช้ birth | ราคาโทเค็น + ราคา 1 ครั้งของ /tarot |
dream | AI ทำนายฝัน | เนื้อหาความฝันใน dream — ไม่ต้องใช้ birth | ราคาโทเค็น + ราคา 1 ครั้งของ /dream |
- การคิดค่าบริการ: ราคาโทเค็น (คำถาม + persona + บล็อกหลักฐานของ AI ตัวนั้นเพียงบล็อกเดียว จำนวนตัวอักษร × 0.25 เป็นโทเค็นขาเข้า และโทเค็นขาออก) + ค่าบริการคงที่ของรายการนั้น 1 รายการ ราคาโดยประมาณต่อ 1 ครั้งแยกตามโดเมนอยู่ที่ ราคา
- ใช้ร่วมกับ
excludeไม่ได้: หากส่งทั้งสองจะได้ 400ONLY_WITH_EXCLUDEหากไม่มีอินพุตที่ AI ตัวนั้นต้องใช้จะได้ 400ONLY_REQUIRES_INPUTหากฟีเจอร์นั้นปิดในบัญชีจะได้ 400ONLY_DOMAIN_UNAVAILABLE— จะไม่ตอบแทนด้วยการอ่านซาจู หากเป็นวันที่ที่คำนวณผังดวง · ผังไม่ได้จะได้ 400ONLY_INPUT_INVALID tarot·dreamไม่ต้องใช้วันเดือนปีเกิด ส่งแค่คำถามและไพ่ (หรือเนื้อหาความฝัน) โดยไม่ต้องมีbirth·sajuก็ได้onlyที่ไม่ใช่sajuไม่ใช้ซาจู การตอบกลับจึงไม่มีsajuSource- สวิตช์ฟีเจอร์: ใช้การตั้งค่าเซิร์ฟเวอร์เดียวกับรายการที่รวมอยู่และตอนนี้เปิดอยู่ หากปิดการตั้งค่า
onlyจะถูกละเว้นและทำงานเหมือนการอ่านดวงซาจูเดิม
ตัวอย่างคำขอ — เฉพาะ AI ไพ่ทาโรต์ (POST /api/v1/partners/v1/reading)
{
"question": "Should I keep pushing ahead with the job change I'm preparing?",
"only": "tarot",
"tarot": { "spread": "past-present-future" }
}
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"interpretation": "과거 자리의 완드의 10 역방향은 오래 짊어진 짐을...",
"only": "tarot",
"modulesUsed": ["tarot"],
"moduleFees": { "tarot": 20 },
"tarot": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": null,
"cards": [
{ "position": 1, "positionLabel": "과거", "id": "wands_10", "name": "완드의 10", "nameEn": "Ten of Wands", "arcana": "wands", "reversed": true, "keywords": ["내려놓기", "위임", "해방"], "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.", "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp" }
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp"
},
"usage": {
"inputTokens": 1180,
"outputTokens": 720
},
"costPoints": 37
}
}
ข้อควรระวัง
- คืนเฉพาะผลการตีความ: การตอบกลับมีเพียงข้อความการตีความดวงที่สร้างขึ้น ไม่เปิดเผยพรอมต์ภายในหรือทฤษฎีซาจู
candorApplied: เฉพาะเมื่อส่งcandorเป็นtการตอบกลับจะมีโทนคำพูดที่ใช้จริง (t|f) แนบมา/reading/memoryก็เหมือนกัน (โทนคำพูด (ชื่อชั่วคราว))- เกณฑ์การคิดค่าบริการ: ขาเข้า = (จำนวนตัวอักษร question + persona) × 0.25 โทเค็น (+ จำนวนตัวอักษรคำบรรยาย YouTube ที่แทรกใน
/reading× 0.25) ขาออก = โทเค็น completion จริง การแทรกซาจู · พรอมต์ระบบไม่คิดค่าบริการ และusage.inputTokensมีไว้เพื่ออ้างอิง หากเปิดรายการที่รวมอยู่ (ดวงวันนี้ · จื่อเวยโต่วซู่ · โหราศาสตร์ตะวันตก · ทำนายฝัน · ไพ่ทาโรต์) จะบวกบล็อกหลักฐานนั้นและค่าบริการคงที่ต่อรายการ costPoints คือยอดที่หักจริง - ภาษาของการตอบกลับ: คำถามที่ไม่ใช่ภาษาเกาหลีจะตอบเป็นภาษาเดียวกับคำถาม
- ไม่ทราบเวลาเกิด: หากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน
API AI อ่านดวงซาจู · หน่วยความจำ
โฮสต์ความจำการสนทนาแยกตามผู้ใช้ปลายทาง และอ่านดวงต่อจากบริบทในอดีตเมื่อกลับมาใช้อีกครั้ง มอบประสบการณ์การปรึกษาต่อเนื่องแบบเฉพาะบุคคล ราคาเป็น 1.3 เท่าของราคาโทเค็นของ AI อ่านดวงซาจู (ต่อ 1M โทเค็น ขาเข้า 3,754 วอน · ขาออก 30,030 วอน — การอ่านดวงคือขาเข้า 2,888 วอน · ขาออก 23,100 วอน ไม่รวม VAT)
POST /api/v1/partners/v1/reading/memory
สร้างการอ่านดวงซาจูด้วย AI จากความจำของผู้ใช้ปลายทางแต่ละคน
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
endUserId |
string | O | ID ผู้ใช้ปลายทางที่พาร์ทเนอร์ออกให้ (ต้องไม่ซ้ำกัน) |
speed |
string | fast (ค่าเริ่มต้น ตอบเร็ว) | value (ตอบช้า ลดราคา 20%) |
|
birth |
object | birth หรือ saju อย่างใดอย่างหนึ่ง | {year, month, day, hour?, minute?, gender, calendar?} calendar: solar (ค่าเริ่มต้น) | lunar — ปฏิทินจันทรคติจะแปลงเป็นสุริยคติแล้วคำนวณ สถานที่เกิด · เขตเวลา · เดือนอธิกมาส (2026-10-17): รับฟิลด์ไม่บังคับ isLeapMonth · timezone · birthLatitude · birthLongitude · country · zaSiRule · birthTimePrecision ด้วยชื่อเดียวกันและกฎเดียวกับ API ปฏิทินหมื่นปี ข้อมูลการเกิดเดียวกันจึงได้สี่เสาเหมือนปฏิทินหมื่นปี พิกัดต้องส่งทั้งสองค่า หากส่งค่าเดียวจะได้ 400 INVALID_LOCATION หากไม่ส่งเลยจะคำนวณเหมือนเดิมทุกอย่าง (เวลาเกิดเป็นเวลาเกาหลี ปฏิทินจันทรคติเป็นเดือนปกติ) ส่วนโหราศาสตร์ตะวันตกจะวาดผังจากเวลาที่ใช้จริงใน timezone ณ เวลาเกิดนั้น (รวมเวลาออมแสง) และพิกัด หากไม่รู้จัก birth.timezone การตอบกลับจะมี warnings (field: "birth.timezone") แนบมา |
saju |
object | birth หรือ saju อย่างใดอย่างหนึ่ง | ป้อนสี่เสาโดยตรง {"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}} หากส่งพร้อม birth จะตรวจสอบไขว้แล้วยึด saju ก่อน (sajuMismatch) |
year / month / day / gender |
number / string | ฟิลด์แบบแบน (แบบเก่า) จะถือเป็น birth (สุริยคติ) เฉพาะเมื่อมีค่าครบทั้งสี่ หากไม่มีทั้ง birth · saju · ฟิลด์แบบแบน จะได้ 400 MISSING_SUBJECT_INPUT |
|
hour / minute |
number | ชั่วโมงเกิด 0-23 / นาที 0-59 (ไม่บังคับ) หากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน | |
question |
string | O | คำถามเกี่ยวกับการอ่านดวง |
tone |
string | โทนการตอบ ("formal", "casual", "warm" ค่าเริ่มต้น: "warm") | |
candor |
string | โทนคำพูด — ระดับความตรงไปตรงมาของคำตอบ t / f (ค่าเริ่มต้น) ไม่คิดค่าบริการ ดู โทนคำพูด (ชื่อชั่วคราว) |
|
persona |
string | ตัวละครที่แอปเลือก (ชื่อ · สำนวน · ท่าที สูงสุด 2,000 ตัวอักษร) ใช้กับสำนวนเท่านั้น และไม่มีลำดับความสำคัญเหนือการตีความซาจู · ขอบเขตความปลอดภัย · คำสั่งเรื่องความยาว คิดค่าบริการเป็นอินพุตเหมือนคำถาม (จำนวนตัวอักษร × 0.25) หากมีหลายตัวละคร ให้เลือกจากรายการที่อนุญาตบนเซิร์ฟเวอร์แล้วส่ง — อย่าใส่ข้อความที่เบราว์เซอร์ส่งมาโดยตรง | |
tagFilter |
string[] | ตัวกรองแท็กหน่วยความจำที่จะค้นหา (ไม่บังคับ) | |
maxLength |
number | ความยาวการตอบสูงสุด (100~2,000 ค่าเริ่มต้น: 800) | |
recallCount |
number | จำนวนความจำในอดีตที่จะระลึก (0~20 ค่าเริ่มต้น 3) | |
tools |
object | แฟล็กฟีเจอร์เพิ่มเติม ตัวอย่าง: {"astrology": true} คีย์ที่ไม่รู้จักจะได้ 400 UNKNOWN_TOOL |
พารามิเตอร์คำขอ — ตัวเลือก tools
| ตัวเลือก | ชนิด | คำอธิบาย |
|---|---|---|
astrology |
boolean | เมื่อเป็น true จะนำผังดวงกำเนิด (Natal Chart) ของโหราศาสตร์ตะวันตกมาใช้ในการอ่านดวง ไม่มีค่าบริการแยก |
fileIds |
string[] | ID เอกสารที่จะแทรก (UUID สูงสุด 5 รายการ) หากละไว้จะระลึกเอกสารวิเคราะห์ที่มีแท็กตรงกับคำถามอัตโนมัติ (filesRecalled) |
emotion / summaryEvery |
boolean / integer | วิเคราะห์สภาวะอารมณ์ (การตอบกลับ emotion) / รอบการอัปเดตสรุป · อารมณ์ 1~20 (ค่าเริ่มต้น 5) |
youtube |
boolean | การแทรก YouTube รองรับเฉพาะใน /reading (/reading/memory ยังไม่รองรับ) — ส่งไปก็จะไม่แทรกคำบรรยาย |
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"interpretation": "당신의 사주에서 보이는 특징은...",
"sajuSource": "computed",
"memory": {
"used": true,
"summaryInjected": false,
"notesInjected": 2,
"tags": ["직장"],
"overheadTokens": 120
},
"usage": {
"inputTokens": 750,
"outputTokens": 380
},
"costPoints": 36,
"toolsUsed": ["memory"]
}
}
ฟิลด์การตอบกลับอื่นๆ (sajuMismatch, toolsSkipped, filesUsed) เหมือนกับ API AI อ่านดวงซาจู เอกสารที่ระลึกอัตโนมัติจะอยู่ใน filesRecalled และถ้า tools.emotion: true จะมี emotion แนบมา เกณฑ์การคิดค่าบริการ (ยกเว้น YouTube) ก็เหมือนกับ API การอ่านดวง
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/reading/memory \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"endUserId": "member-1024",
"question": "About the job change we talked about last time: is next month a good time to make the move?",
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female" }
}'
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | MISSING_ENDUSER_ID | endUserId ว่างหรือมีแต่ช่องว่าง |
| 400 | MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE | ข้อมูลการเกิด · อินพุตซาจูผิดพลาด (เหมือน API การอ่านดวง) |
| 400 | UNKNOWN_TOOL · INVALID_TOOL_MODE · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUND | tools · fileIds ผิดพลาด เส้นทางนี้รับ tools.emotion · tools.summaryEvery ด้วย |
| 400 | ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALID | ข้อผิดพลาดที่เกี่ยวกับการเรียก AI ตัวเดียวแยก |
| 402 | INSUFFICIENT_BALANCE | จองค่าขาออกล่วงหน้าไม่ได้ (วิธีเดียวกับ API การอ่านดวง) |
| 403 | FEATURE_DISABLED | ใช้ฟีเจอร์ที่ปิดในบัญชี (youtube · files · emotion) |
API จัดการหน่วยความจำ
AI อ่านดวงซาจูแบบหน่วยความจำ (POST /reading/memory) และแชต RIDM (user ของโมเดล ridm/*) ใช้คลังความจำของผู้ใช้ปลายทางเดียวกัน {endUserId} ในเส้นทางด้านล่างคือค่าที่ส่งไปในตอนนั้นตามเดิม (เช่น หากแบ่งแชตเป็นรายเซสชัน ก็คือคีย์ทั้งหมดอย่าง memberId:chatId)
| เอนด์พอยต์ | เมธอด | คำอธิบาย |
|---|---|---|
| /api/v1/partners/v1/memory/{endUserId} | GET | ดึงหน่วยความจำที่เก็บของผู้ใช้ปลายทาง → {endUserId, summary, metaSummary, tags, profile, concerns, facts} (profile · facts ตอนนี้เป็น null / [] เสมอ) |
| /api/v1/partners/v1/memory/{endUserId}/messages | GET | ดึงรายการข้อความของผู้ใช้ปลายทาง คิวรี limit (ค่าเริ่มต้น 50 สูงสุด 200) · offset → {endUserId, messages:[{id, role, content, tags, createdAt}], offset, limit, total} |
| /api/v1/partners/v1/memory/search?endUserId={endUserId}&tags=… | GET | ค้นหาแท็กหน่วยความจำ (tags คั่นด้วยจุลภาค รวมอยู่ในค่าบริการหน่วยความจำ RIDM ไม่มีค่าบริการแยก) → {endUserId, query:{tags}, results} (results สูงสุด 20 รายการ) |
| /api/v1/partners/v1/memory/{endUserId}/turns | POST | เก็บบทสนทนาที่คุยไปแล้ว (เช่น การปรึกษาทางโทรศัพท์ด้วย AI) ตามเดิมโดยไม่ให้ AI สร้าง เนื้อหา {messages:[{role, content}], summary?, tags?} — role คือ user · assistant, messages 1~50 รายการ, content สูงสุด 4,000 ตัวอักษร, summary สูงสุด 1,500 ตัวอักษร, tags สูงสุด 10 รายการ (รายการละ 30 ตัวอักษร) เก็บตามลำดับที่ส่ง และ tags จะติดกับทุกเทิร์น หากให้ summary จะแสดงเป็น summary ของ GET /memory/{endUserId} หากเป็น endUserId ที่ไม่เคยเห็นจะสร้างใหม่ ไม่มีการเรียก AI จึงไม่มีค่าบริการแยก → {endUserId, saved, summarySaved} (เฉพาะคีย์เซิร์ฟเวอร์) |
| /api/v1/partners/v1/memory/{endUserId} | DELETE | ลบหน่วยความจำทั้งหมดของผู้ใช้ปลายทาง รวมถึงไฟล์ที่อัปโหลดด้วยผู้ใช้ปลายทางนั้น (/files) → 204 (ไม่มีเนื้อหา) |
ตัวอย่างคำขอ · การตอบกลับ
# Get stored memory
curl https://api.hrum.ai/api/v1/partners/v1/memory/member-1024 \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"summary": "이직을 고민 중이며 다음 달 면접을 앞두고 있다...",
"metaSummary": "...",
"tags": ["이직", "면접"],
"profile": null,
"concerns": ["..."],
"facts": []
}
}
# Message list (oldest first)
curl "https://api.hrum.ai/api/v1/partners/v1/memory/member-1024/messages?limit=2&offset=0" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"messages": [
{ "id": "...", "role": "user", "content": "이직 고민이 있어요", "tags": ["이직"], "createdAt": "2026-10-11T09:00:00.000Z" },
{ "id": "...", "role": "assistant", "content": "...", "tags": [], "createdAt": "2026-10-11T09:00:04.000Z" }
],
"offset": 0,
"limit": 2,
"total": 18
}
}
# Tag search (tags as stored: 이직 = job change, 면접 = interview)
curl "https://api.hrum.ai/api/v1/partners/v1/memory/search?endUserId=member-1024&tags=이직,면접" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"query": { "tags": ["이직", "면접"] },
"results": [
{ "id": "...", "summary": "다음 달 면접 일정을 이야기함", "level": 0, "tags": ["면접"], "createdAt": "2026-10-11T09:00:00.000Z" }
]
}
}
# Save a conversation (no AI generation)
curl -X POST https://api.hrum.ai/api/v1/partners/v1/memory/member-1024/turns \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "I'\''m worried about my interview next month" },
{ "role": "assistant", "content": "You'\''ve prepared well. You'\''ll do fine." }
],
"summary": "Call about feeling anxious before next month'\''s interview",
"tags": ["interview"]
}'
{
"success": true,
"data": {
"endUserId": "member-1024",
"saved": 2,
"summarySaved": true
}
}
# Delete everything (memory + uploaded files) — 204, no body
curl -X DELETE https://api.hrum.ai/api/v1/partners/v1/memory/member-1024 \
-H "X-Partner-Api-Key: your-api-key"
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | END_USER_NOT_FOUND | endUserId ที่ไม่เคยเห็น (ใช้ร่วมกันใน 4 เส้นทาง ยกเว้นการเก็บบทสนทนา) |
| 400 | MISSING_PARAM | การค้นหา — ไม่มี endUserId |
| 400 | MISSING_TAGS | การค้นหา — tags ว่าง |
| 400 | ENDUSER_ID_TOO_LONG | การเก็บบทสนทนา — endUserId เกิน 255 ตัวอักษร |
ข้อควรระวัง
- ราคา 1.3 เท่า: เนื่องจากการโฮสต์หน่วยความจำ ราคาโทเค็นขาเข้า/ขาออกจึงเป็น 1.3 เท่าของ AI อ่านดวงซาจู (ต่อ 1M โทเค็น ขาเข้า 3,754 วอน · ขาออก 30,030 วอน ไม่รวม VAT)
- ต้องมี endUserId: ผู้ใช้ปลายทางแต่ละคนต้องมี ID ที่ไม่ซ้ำกัน และเมื่อเรียกด้วย ID เดียวกัน บริบทในอดีตจะถูกคงไว้
- การเก็บรักษาหน่วยความจำ: หน่วยความจำที่เก็บไว้จะถูกเก็บรักษาจนกว่าจะลบอย่างชัดแจ้ง
API รายงานซาจู
ไม่ต้องถาม แค่กดปุ่มครั้งเดียวก็ได้การตีความซาจูทั้งหมดในครั้งเดียว ตั้งแต่ภาพรวม · การเงิน · ความรัก · วัยจร 10 ปี เป็นสินค้าแบบชำระเงินรายชิ้นที่แยกจากแบบสนทนา (reading) ค่าเริ่มต้นคือโมเดลเฉพาะ ridm/saju-report (โมเดลเฉพาะทางด้านรายงานของ RIDM เอง — ด้วยลักษณะของสินค้าแบบครั้งเดียวจึงไม่มีหน่วยความจำ) เพดานการตอบของ API การอ่านดวงคือ 2,000 ตัวอักษร — หากต้องการคำอธิบายยาวกว่านั้น (สูงสุด 12 หัวข้อ ประมาณ 6,000 ตัวอักษร) ให้ใช้ API รายงานนี้
POST /api/v1/partners/v1/reading/report
ใส่วันเดือนปีเกิด (หรือซาจู) แล้วจะคืนรายงานซาจูแบบ Markdown แยกตามหัวข้อ
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
| birth | object | birth หรือ saju อย่างใดอย่างหนึ่ง | {year, month, day, hour?, minute?, gender, calendar?} — calendar: "lunar" จะแปลงเป็นสุริยคติแล้วคำนวณ สถานที่เกิด · เขตเวลา · เดือนอธิกมาส (2026-10-17): รับฟิลด์ไม่บังคับ isLeapMonth · timezone · birthLatitude · birthLongitude · country · zaSiRule · birthTimePrecision ด้วยชื่อเดียวกันและกฎเดียวกับ API ปฏิทินหมื่นปี ข้อมูลการเกิดเดียวกันจึงได้สี่เสาเหมือนปฏิทินหมื่นปี พิกัดต้องส่งทั้งสองค่า หากส่งค่าเดียวจะได้ 400 INVALID_LOCATION หากไม่ส่งเลยจะคำนวณเหมือนเดิมทุกอย่าง (เวลาเกิดเป็นเวลาเกาหลี ปฏิทินจันทรคติเป็นเดือนปกติ) ส่วนโหราศาสตร์ตะวันตกจะวาดผังจากเวลาที่ใช้จริงใน timezone ณ เวลาเกิดนั้น (รวมเวลาออมแสง) และพิกัด หากไม่รู้จัก birth.timezone การตอบกลับจะมี warnings (field: "birth.timezone") แนบมา |
| saju | object | birth หรือ saju อย่างใดอย่างหนึ่ง | ป้อนสี่เสาโดยตรง {"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}} |
| year / month / day / gender | number / string | ไม่บังคับ | ฟิลด์แบบแบน (แบบเก่า สุริยคติ) จะถือเป็น birth เฉพาะเมื่อมีค่าครบทั้งสี่ หากไม่มีทั้ง birth · saju จะได้ 400 MISSING_SUBJECT_INPUT |
| hour / minute | number | ไม่บังคับ | หากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน หากส่ง minute โดยไม่มี hour จะถูกละเว้น |
| tone | string | ไม่บังคับ | warm (ค่าเริ่มต้น) | casual | formal |
| candor | string | ไม่บังคับ | โทนคำพูด — t | f (ค่าเริ่มต้น) เปลี่ยนเพียงการจัดวาง · ความเข้มของข้อดีและข้อยาก ส่วนโครงสร้างหัวข้อ · ข้อห้ามการยืนยันด้านการแพทย์ · กฎหมาย · การลงทุนยังคงเดิม ไม่คิดค่าบริการ ดู โทนคำพูด (ชื่อชั่วคราว) |
| persona | string | ไม่บังคับ | คำสั่งเรื่องสำนวน · ตัวละคร (สูงสุด 2,000 ตัวอักษร — คิดค่าบริการขาเข้าเฉพาะความยาวนี้) |
| sections | string[] | ไม่บังคับ | รายการชื่อหัวข้อ (1~12 รายการ ชื่อละไม่เกิน 30 ตัวอักษร) ค่าเริ่มต้น 8 หัวข้อ: 총평 · 타고난 기질 · 재물운 · 연애·인연 · 직업·적성 · 올해와 내년 · 10년 대운 흐름 · 마지막 한 줄 처방 |
รายงานเขียนเป็นภาษาเกาหลีเสมอ หากส่งฟิลด์ที่ไม่มีในตารางข้างบน เช่น speed · tools · lang · question จะถูกปฏิเสธด้วย 400
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/reading/report \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female" },
"sections": ["총평", "재물운", "연애·인연"]
}'
การตอบกลับ
{
"success": true,
"data": {
"report": "## 총평\n...", // full Markdown, section by section
"sections": ["총평", "..."],
"sajuSource": "computed",
"usage": { "inputTokens": 5756, "outputTokens": 2019 },
"costPoints": 77,
"model": "ridm/saju-report"
// "candorApplied": "t" — only when candor was sent as t (t | f)
}
}
- แทรกซาจูฟรี: การคำนวณ · แทรกปฏิทินหมื่นปีและพรอมต์ระบบไม่คิดค่าบริการ ขาเข้าคิดเฉพาะความยาว persona ขาออกคิดตามโทเค็นที่ใช้จริง
- ค่าใช้จ่ายที่วัดจริง: รายงานค่าเริ่มต้น 8 หัวข้อ (ประมาณ 3,000 ตัวอักษร) 1 ครั้งประมาณ 85P (ตามขาออก ₩38,077/1M)
- การลองใหม่จะคิดค่าบริการอีกครั้ง หากต้องการนำผลของอินพุตเดิมกลับมาใช้หลังได้รับการตอบกลับ ให้เก็บไว้ฝั่งไคลเอนต์ (Idempotency)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | MISSING_SUBJECT_INPUT | ไม่มีทั้ง birth · saju |
| 400 | INVALID_SAJU_PILLAR | เสาใน saju ไม่อยู่ในวงรอบ 60 คู่ (หกสิบกะจื่อ) |
| 400 | INVALID_LUNAR_DATE | วันที่ตามปฏิทินจันทรคติที่ไม่มีอยู่จริง |
| 402 | INSUFFICIENT_BALANCE | จองค่าขาออกของความยาวรายงานสูงสุด (6,000 โทเค็น) ล่วงหน้าไม่ได้ |
API สรุป YouTube
ดึงคำบรรยายของวิดีโอ YouTube แล้วให้บริการสรุปและวิเคราะห์ถาม-ตอบ (Q&A) หากไม่มีคำบรรยายจะได้ข้อผิดพลาด 400 (ไม่คิดค่าบริการ)
POST /api/v1/partners/v1/youtube/summary
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
url |
string | O | URL ของ YouTube (เช่น https://www.youtube.com/watch?v=dQw4w9WgXcQ) หรือ ID วิดีโอ 11 หลัก |
question |
string | คำถามเฉพาะ (ไม่บังคับ — หากมีจะเป็นโหมด Q&A) | |
maxLength |
number | เป้าหมายความยาวของสรุป (100~4,000 ค่าเริ่มต้น 1,000) ใช้เป็นงบโทเค็นขาออก ไม่รับประกันจำนวนตัวอักษรที่แน่นอน | |
tone |
string | เลือกโทน: warm | casual | formal (ค่าเริ่มต้น: casual) จะถูกละเว้นในโหมด question (Q&A) | |
lang |
string | ภาษาของคำบรรยายที่จะดึง (ค่าเริ่มต้น: ko) การสรุป (ไม่มี question) เขียนเป็นภาษาเกาหลีไม่ว่าภาษาใด ส่วนโหมด question (Q&A) ตอบเป็นภาษาของคำถามได้ |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/youtube/summary \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "maxLength": 1000 }'
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"summary": "## 0:00~1:30 오프닝\n영상 제목 설명...\n\n## 1:30~5:00 본론\n...",
"video": {
"videoId": "dQw4w9WgXcQ",
"title": "Video Title",
"channel": "Channel Name"
},
"transcriptSource": "supadata",
"usage": {
"promptTokens": 7059,
"completionTokens": 1384
},
"costPoints": 51,
"model": "ridm/gpt-5.6-terra"
}
}
ข้อควรระวัง
- ต้องมีคำบรรยาย: หากไม่มีคำบรรยายจะได้ TRANSCRIPT_UNAVAILABLE 400 (ไม่คิดค่าบริการ)
- ข้อผิดพลาด: URL · ID ไม่ถูกต้อง 400
INVALID_YOUTUBE_URL/ สร้างสรุปล้มเหลว 400LLM_GENERATION_FAILED/ ยอดคงเหลือไม่พอ 402INSUFFICIENT_BALANCE - การคิดค่าบริการ: คิดตามโทเค็น ใช้ราคาขายต่อตามเดิม (ต้นทุน × 1.1) ของโมเดลที่ใช้ (ค่าเริ่มต้น
ridm/gpt-5.6-terra) — ไม่มีเลเยอร์หน่วยความจำ จึงไม่ใช้ราคา RIDM Memory (× 1.3) costPoints = ปัดขึ้น (โทเค็นขาเข้า × ราคาขาเข้า + โทเค็นขาออก × ราคาขาออก) ราคาคิดต่อ 1M โทเค็น (ไม่รวม VAT) - ค่าใช้จ่ายที่วัดจริง: วิดีโอ 20~30 นาที 1 ครั้งประมาณ 60P (รวมโทเค็น)
- เชื่อมกับการอ่านดวง: ใน API AI อ่านดวงซาจู (
/reading) แทรกคำบรรยายของลิงก์ในคำถามได้ด้วยtools: { "youtube": true }(ฟิลด์youtubeระดับบนสุดจะถูกละเว้น) การแทรก YouTube รองรับเฉพาะใน /reading (/reading/memory ยังไม่รองรับ) หากส่งไปที่ /reading/memory จะไม่ดึงคำบรรยาย และแจ้งในtoolsSkippedเป็น{"tool": "youtube", "reason": "unavailable"}
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | INVALID_YOUTUBE_URL | หา ID วิดีโอใน URL ไม่พบ |
| 400 | TRANSCRIPT_UNAVAILABLE | วิดีโอที่ไม่มีคำบรรยาย (ไม่คิดค่าบริการ) |
| 400 | LLM_GENERATION_FAILED | สร้างสรุปล้มเหลวหรือได้ผลลัพธ์ว่าง |
| 402 | INSUFFICIENT_BALANCE | จองค่าสรุปล่วงหน้าไม่ได้ |
| 403 | FEATURE_DISABLED | ฟีเจอร์ YouTube ถูกปิดในบัญชี |
เปิด-ปิดฟีเจอร์
API สรุป YouTube เลือกเปิดใช้ (opt-in) ได้ทั้งระดับบัญชีพาร์ทเนอร์และระดับคำขอ จัดการสถานะเปิดใช้งานทั้งระบบได้ที่ "ตั้งค่าฟีเจอร์" ในคอนโซล และเปิดใช้รายคำขอโดยระบุ youtube:true ระดับบนสุดสำหรับ chat และ tools: { "youtube": true } สำหรับ reading
- ปิดทั้งระบบ: ตอบกลับ 403 { code: 'FEATURE_DISABLED', feature: 'youtube' }
- ระดับคำขอ: ไม่ระบุ
youtube:trueหรือเป็น false = ไม่แทรก YouTube
API ประมวลผลเอกสาร
อัปโหลดเอกสาร PDF, Word (.docx), Excel (.xlsx), PowerPoint (.pptx), CSV, ข้อความ, Markdown, ฮันกึล (.hwpx) แล้ววิเคราะห์ด้วย AI เพื่อนำเข้าสู่ฐานความรู้ตามบริบทได้ เอกสารจะถูกดึงข้อความอัตโนมัติ และหากเปิดตัวเลือก "วิเคราะห์ด้วย AI" จะแบ่งเอกสารเป็นช่วงตามบริบท แล้วสร้างสรุปและแท็กค้นหาของแต่ละช่วงเก็บไว้
รูปแบบที่รองรับและข้อจำกัด
| รายการ | ข้อกำหนด |
|---|---|
| รูปแบบที่รองรับ | .pdf, .docx, .xlsx, .pptx, .csv, .txt, .md, .hwpx (ไม่รองรับ .hwp ของฮันกึลรุ่นเก่า) |
| ขนาดไฟล์สูงสุด | 10 MB |
| ข้อความที่ดึงได้สูงสุด | 200,000 ตัวอักษร (หากเกินจะแสดง charsCapped: true) |
| ไฟล์สูงสุดต่อคำขอ | 5 ไฟล์ (fileIds) |
| ขนาดที่แทรกใน chat | สูงสุด 40,000 ตัวอักษรต่อไฟล์ / รวม 80,000 ตัวอักษร |
| ช่วงจำนวนชิ้นการวิเคราะห์ | 3~8 ช่วง (เอกสารยาว 40,000 ตัวอักษรขึ้นไปจะวิเคราะห์ 2 รอบ) |
| ช่วงจำนวนแท็ก | สูงสุด 10 แท็กต่อช่วง รวมทั้งหมดสูงสุด 10 แท็ก |
เอนด์พอยต์
| เมธอด | เส้นทาง | คำอธิบาย |
|---|---|---|
| POST | /api/v1/partners/v1/files |
อัปโหลดไฟล์ (multipart) |
| GET | /api/v1/partners/v1/files |
ดึงรายการไฟล์ (ขอบเขตพาร์ทเนอร์) คิวรี endUserId, limit (ค่าเริ่มต้น 20 สูงสุด 100), offset → {files, total, limit, offset} |
| GET | /api/v1/partners/v1/files/:id |
ดึงรายละเอียดไฟล์ (รวมข้อความที่ดึงได้) |
| DELETE | /api/v1/partners/v1/files/:id |
ลบไฟล์ |
อัปโหลดไฟล์
POST /api/v1/partners/v1/files
อัปโหลดไฟล์ในรูปแบบ Multipart form
ฟิลด์คำขอ
| ฟิลด์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
file |
binary | O | ไฟล์ที่อัปโหลด |
endUserId |
string | ID ผู้ใช้ปลายทาง (จำเป็นเมื่อวิเคราะห์) | |
analyze |
'true'|'false' | เปิดการวิเคราะห์ด้วย AI (ค่าเริ่มต้น: 'false') |
ตัวอย่าง cURL
curl -X POST https://api.hrum.ai/api/v1/partners/v1/files \
-H "X-Partner-Api-Key: YOUR_API_KEY" \
-F "[email protected]" \
-F "endUserId=user_123" \
-F "analyze=true"
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "sample.pdf",
"originalName": "sample.pdf",
"mime": "application/pdf",
"size": 125000,
"textLength": 8942,
"charsCapped": false,
"textPreview": "1장. 개요 ...",
"summary": "문서 전체 요약...",
"context": "문서 전체 요약...",
"status": "analyzed",
"analysisStatus": "analyzed",
"analyzeRequested": true,
"endUserId": "user_123",
"usage": { "inputTokens": 3100, "outputTokens": 420, "costWon": 1 },
"totalChunks": 3,
"createdAt": "2026-08-26T12:34:56Z"
}
}
รายการ · รายละเอียด · ลบ
# List — newest first, limit 1–100 (default 20)
curl "https://api.hrum.ai/api/v1/partners/v1/files?endUserId=user_123&limit=20&offset=0" \
-H "X-Partner-Api-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"files": [ { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "name": "sample.pdf", "status": "analyzed", ... } ],
"total": 1,
"limit": 20,
"offset": 0
}
}
# Details — upload response fields + extractedText + chunks
curl https://api.hrum.ai/api/v1/partners/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "X-Partner-Api-Key: YOUR_API_KEY"
{
"success": true,
"data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "sample.pdf",
...,
"extractedText": "1장. 개요 ...",
"chunks": [
{ "id": "...", "chunkIndex": 0, "context": "1장 요약...", "tags": ["개요"], "textLength": 2980 }
]
}
}
# Delete
curl -X DELETE https://api.hrum.ai/api/v1/partners/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "X-Partner-Api-Key: YOUR_API_KEY"
{ "success": true, "data": { "deleted": true } }
การเชื่อมกับ Chat และการอ่านดวง
แนบแบบระบุชัด: เมื่อขอ Chat completions หรือการอ่านดวงด้วย AI สามารถแทรกเอกสารได้สูงสุด 5 รายการด้วยพารามิเตอร์ fileIds ไฟล์ที่วิเคราะห์แล้วจะแทรกสรุปเอกสาร (สูงสุด 500 ตัวอักษร) และข้อความต้นฉบับ ส่วนไฟล์ที่ยังไม่วิเคราะห์จะแทรกข้อความต้นฉบับ (ต้นฉบับจำกัด 40,000 ตัวอักษรต่อไฟล์ / รวม 80,000 ตัวอักษร ไม่แทรกชิ้นย่อย) เอกสารที่แทรกจะถูกเพิ่มต่อท้ายข้อความผู้ใช้ล่าสุดและรวมอยู่ในโทเค็นขาเข้า โมเดลขายต่อรองรับเฉพาะการแทรก fileIds แบบระบุชัด
ระลึกอัตโนมัติ (เฉพาะ ridm/*): ในโมเดล ridm/* chat และ reading-memory จะค้นหาไฟล์ที่วิเคราะห์แล้วซึ่งมีแท็กตรงกับคำถามผู้ใช้แล้วแทรกให้อัตโนมัติ (เฉพาะเมื่อไม่ได้ระบุ fileIds) การตอบกลับจะแสดง ID ไฟล์ที่ระลึกได้ในอาร์เรย์ filesRecalled
ตัวอย่างคำขอ Chat
{
"model": "ridm/gpt-5.6-terra",
"messages": [
{ "role": "user", "content": "Can you summarize the main points of this document?" }
],
"fileIds": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"],
"user": "user_123"
}
ตัวอย่างการตอบกลับ
{
"id": "chatcmpl-abc123",
"choices": [{
"message": { "content": "문서의 주요 내용은..." },
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 2500, "completion_tokens": 150 },
"filesUsed": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"]
}
filesRecalled จะแนบมาเฉพาะเมื่อมีไฟล์ที่ระลึกอัตโนมัติ (หากว่างจะละไว้)
ราคาและการคิดค่าบริการ
- อัปโหลดและดึงข้อความ: ฟรี (ไม่คิดค่าโทเค็นการดึงข้อความ)
- วิเคราะห์ด้วย AI (analyze=true): คิดค่าบริการตามโทเค็นที่ใช้จริงในการตรวจหาขอบเขต + สรุปแต่ละช่วง + สรุปทั้งหมด ในราคาของโมเดลวิเคราะห์ แบบซิงโครนัส ≤30,000 ตัวอักษร แบบอะซิงโครนัส >30,000 ตัวอักษร (status:
analyzing) - การแทรกใน Chat: ข้อความเอกสารนับเป็นโทเค็นขาเข้าและคิดค่าบริการเหมือนคำขอ chat ทั่วไป
- บันทึก: ตรวจสอบได้ในบันทึกการใช้งานของคอนโซลตามหมวด
file_upload(ฟรี),file_analyze(มีค่าใช้จ่าย ตามโทเค็นที่ใช้จริง)
เปิด-ปิดฟีเจอร์
ฟีเจอร์ประมวลผลเอกสารเปิด/ปิดได้ที่ระดับบัญชีพาร์ทเนอร์ จัดการได้ที่ "ตั้งค่าฟีเจอร์" ในคอนโซล เมื่อปิด คำขอไฟล์ทั้งหมดจะได้การตอบกลับ 403
- ปิดทั้งระบบ: ตอบกลับ 403 { code: 'FEATURE_DISABLED', feature: 'files' }
- ระดับคำขอ: ไม่ระบุ
fileIds= ไม่แทรกเอกสาร (ประมวลผลตามปกติ)
สถานะการวิเคราะห์และชิ้นข้อมูล
การตอบกลับของ GET /api/v1/partners/v1/files/:id มี analysisStatus, extractedText, chunks chunks เป็นอาร์เรย์ (แต่ละชิ้น: chunkIndex, context (สรุป), tags สูงสุด 10 รายการ) เฉพาะเมื่อวิเคราะห์เสร็จและ totalChunks มีค่า 2 ขึ้นไป นอกนั้นเป็น null การตอบกลับของการอัปโหลดไม่มี chunks
| สถานะ | คำอธิบาย |
|---|---|
ready |
ดึงข้อความเสร็จ · ไม่มีการวิเคราะห์ (analyze=false หรือไม่ระบุ — analyzeRequested=false) |
analyzing |
กำลังวิเคราะห์ (แบบอะซิงโครนัสเมื่อเกิน 30,000 ตัวอักษร) |
analyzed |
วิเคราะห์เสร็จ (รวม context · tags · chunks[]) |
analyze_failed |
วิเคราะห์ล้มเหลว (การตอบกลับไม่มีสาเหตุที่ล้มเหลว — อัปโหลดใหม่อีกครั้ง) |
ข้อควรระวัง
- ตรวจสอบรูปแบบ: รูปแบบที่ไม่รองรับจะคืน 400 { code: 'INVALID_FILE_TYPE' }
- ข้อผิดพลาดอื่นๆ: ไม่มีไฟล์ 400
FILE_NOT_PROVIDED/ เกิน 10MB 400FILE_TOO_LARGE/ ไฟล์ไม่มีอยู่ 404FILE_NOT_FOUND/ หาก:idไม่ใช่ UUID จะได้ 400 - จำเป็นสำหรับการวิเคราะห์: เมื่อ analyze=true หากไม่มี endUserId จะคืน 400 { code: 'END_USER_REQUIRED' }
- ดึงข้อความล้มเหลว: หากเกิดข้อผิดพลาดระหว่างดึงข้อความจากเอกสาร จะคืน 422 { code: 'EXTRACTION_FAILED' }
- ตรวจยอดคงเหลือ: ตรวจว่าเครดิตของพาร์ทเนอร์เพียงพอก่อนขอวิเคราะห์ หากไม่พอจะคืน 402
- นำเข้าฐานความรู้อัตโนมัติ: เมื่อ analyze=true สรุปและแท็กของแต่ละช่วงจะถูกเก็บลงฐานความรู้อัตโนมัติ และเป็นเป้าหมายของ auto-recall ในภายหลัง หากระบุ endUserId จะเพิ่มลงในชั้นความจำของผู้ใช้นั้นด้วย
- อัปโหลดซ้ำ = ไฟล์ใหม่: ทุกครั้งที่อัปโหลดจะสร้างไฟล์ใหม่ (id ใหม่) และถ้า analyze=true จะวิเคราะห์และคิดค่าบริการอีกครั้ง เอกสารเดิมให้อัปโหลดครั้งเดียวแล้วนำ id ที่ได้มาใช้ซ้ำเป็น
fileIds
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | FILE_NOT_PROVIDED | อัปโหลด — ไม่มีส่วน file |
| 400 | INVALID_FILE_TYPE | อัปโหลด — รูปแบบที่ไม่รองรับ |
| 400 | FILE_TOO_LARGE | อัปโหลด — เกิน 10MB (บางกรณีเป็น 413 ที่ไม่มีรหัส) |
| 400 | END_USER_REQUIRED | อัปโหลด — analyze=true แต่ไม่มี endUserId |
| 400 | (ไม่มี) | รายละเอียด · ลบ — :id ไม่ใช่ UUID |
| 402 | INSUFFICIENT_BALANCE | อัปโหลด — จองค่าวิเคราะห์ล่วงหน้าไม่ได้ |
| 403 | FEATURE_DISABLED | ฟีเจอร์ประมวลผลเอกสารถูกปิดในบัญชี (ใช้ร่วมกันทั้ง 4 เส้นทาง) |
| 404 | FILE_NOT_FOUND | รายละเอียด · ลบ — ไฟล์ไม่มีอยู่หรือเป็นไฟล์ของบัญชีอื่น |
| 422 | EXTRACTION_FAILED | อัปโหลด — ดึงข้อความจากเอกสารไม่ได้ |
วิเคราะห์สภาวะอารมณ์ (Emotion)
วิเคราะห์สภาวะอารมณ์ของผู้ใช้และ AI โดยอาศัยรอบการสรุปใน Chat API ไม่มีการเรียก LLM แยก และเพิ่มเพียงบล็อกวิเคราะห์อารมณ์ลงในพรอมต์สรุป จึงไม่มีค่าบริการเพิ่ม รองรับเฉพาะโมเดล ridm/*
ภาพรวม
เงื่อนไขการเปิดใช้งาน:
- ทั้งระบบ:
partner_emotion_enabled✓ - Partner: เปิด "วิเคราะห์สภาวะอารมณ์" ในการตั้งค่าฟีเจอร์ของคอนโซล
- Request: ระบุ
emotion: true - Model: รองรับเฉพาะตระกูล
ridm/*
รอบการสรุป (summaryEvery)
การวิเคราะห์อารมณ์จะทำงานอัตโนมัติทุกรอบการสรุป ปรับรอบได้ด้วยพารามิเตอร์ summaryEvery (ค่าเริ่มต้น: 5 ช่วง: 1–20)
- summaryEvery=1: อัปเดตอารมณ์เกือบทุกเทิร์น (การสรุปทำงานแบบอะซิงโครนัสหลังตอบกลับ)
- summaryEvery=5: รอบละ 5 เทิร์น (แนะนำ)
- summaryEvery=20: รอบละ 20 เทิร์น (อัปเดตน้อยที่สุด)
- รอบการสรุป · อารมณ์ไม่คิดค่าบริการกับพาร์ทเนอร์ ไม่ว่ารอบจะเป็นเท่าใด
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
emotion |
boolean | เปิดการวิเคราะห์สภาวะอารมณ์ (เฉพาะโมเดล ridm/* ค่าเริ่มต้น: false) | |
summaryEvery |
number | จำนวนเต็ม 1–20 (ค่าเริ่มต้น 5) รอบการอัปเดตสรุป · อารมณ์ (หน่วยเป็นเทิร์น) |
ตัวอย่างคำขอ
{
"model": "ridm/gpt-5.6-terra",
"user": "user_123",
"messages": [
{ "role": "user", "content": "Today was a rough day..." }
],
"emotion": true,
"summaryEvery": 3
}
ฟิลด์ในการตอบกลับ
| เส้นทางฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
emotion |
object|null | สภาวะอารมณ์ (ก่อนรอบแรกหรือเมื่อ emotion=false จะเป็น null/ไม่มี) |
emotion.user |
object | อารมณ์ของผู้ใช้ |
emotion.user.type10 |
string|null | การตัดสินอารมณ์ 10 คลาส (joyful|calm|curious|concerned|excited|thoughtful|neutral|sad|angry|surprised|null) |
emotion.user.tone |
string|null | โทน (สตริงอิสระ — ไม่ใช่รายการตายตัว เช่น "warm") หรือ null |
emotion.user.distribution6 |
object | การกระจาย 6 คลาส {joy, sadness, anger, fear, disgust, surprise} ผลรวม = 1000 หรือ 0 |
emotion.assistant |
object | อารมณ์ของ AI |
emotion.assistant.distribution6 |
object | การกระจาย 6 คลาสของ AI |
emotion.trend |
string|null | แนวโน้มอารมณ์ (improving|stable|declining|null) |
emotion.updatedAt |
ISO 8601 | เวลาที่อัปเดตอารมณ์ล่าสุด |
emotion.turnsSinceUpdate |
number | จำนวนเทิร์นที่ผ่านไปหลังอัปเดตล่าสุด |
ตัวอย่างการตอบกลับ
{
"id": "chatcmpl-xyz",
"choices": [{
"message": { "content": "오늘 하루가 힘들었군요..." },
"finish_reason": "stop"
}],
"emotion": {
"user": {
"type10": "sad",
"tone": "warm",
"distribution6": {"joy": 100, "sadness": 600, "anger": 50, "fear": 100, "disgust": 50, "surprise": 0}
},
"assistant": {
"distribution6": {"joy": 200, "sadness": 100, "anger": 0, "fear": 0, "disgust": 0, "surprise": 0}
},
"trend": "stable",
"updatedAt": "2026-08-26T12:34:56Z",
"turnsSinceUpdate": 0
},
"usage": {...}
}
คำอธิบายฟิลด์การกระจาย (distribution6)
| อารมณ์ | ค่า | คำอธิบาย |
|---|---|---|
joy |
0–1000 | ความเข้มของความสุข |
sadness |
0–1000 | ความเข้มของความเศร้า |
anger |
0–1000 | ความเข้มของความโกรธ |
fear |
0–1000 | ความเข้มของความกลัว |
disgust |
0–1000 | ความเข้มของความรังเกียจ |
surprise |
0–1000 | ความเข้มของความประหลาดใจ |
การตัดสินแนวโน้ม (trend)
- improving: อารมณ์ที่ไม่ใช่เชิงบวก (sadness+anger+fear+disgust) ลดลง 50 ขึ้นไป
- stable: เปลี่ยนแปลงน้อยกว่า 50
- declining: อารมณ์ที่ไม่ใช่เชิงบวกเพิ่มขึ้น 50 ขึ้นไป
- null: ไม่มีข้อมูลของรอบก่อนหน้า
ตัวอย่างการตอบกลับแบบสตรีมมิง (SSE)
ในโหมดสตรีมมิง (stream: true) สภาวะอารมณ์จะรวมอยู่ในข้อมูลของอีเวนต์ SSE event: message_done
event: message_done
data: {"finish_reason":"stop","usage":{...},"costWon":2,"recalledMemories":[],"memorySaved":{"id":"turn-1756200000000","keywords":[]},"emotion":{"user":{"type10":"concerned","tone":"warm","distribution6":{...}},"assistant":{...},"trend":"stable","updatedAt":"2026-08-26T12:34:56Z","turnsSinceUpdate":0}}
data: [DONE]
ข้อมูลค่าใช้จ่าย
- ไม่มีค่าบริการแยก: การวิเคราะห์อารมณ์ทำงานโดยรวมอยู่ในพรอมต์ของรอบการสรุป และโทเค็นของรอบสรุป · อารมณ์ไม่คิดค่าบริการกับพาร์ทเนอร์ คิดค่าบริการเฉพาะโทเค็นขาเข้า · ขาออกของเทิร์นแชตเท่านั้น
ข้อควรระวัง
- ก่อนรอบแรก: ก่อนรอบการสรุปแรกทำงาน จะไม่มีฟิลด์ emotion (เป็นการทำงานปกติ)
- ฟีเจอร์ปิด: หากเป็นคำขอ
emotion: trueแต่การตั้งค่าฟีเจอร์ทั้งระบบหรือของพาร์ทเนอร์ปิดอยู่ จะตอบกลับ 403 { code: 'FEATURE_DISABLED', feature: 'emotion' } (เหมือน YouTube · การประมวลผลเอกสาร) หากไม่ส่งemotionหรือเป็น false จะละเฉพาะฟิลด์ - รองรับเฉพาะโมเดล ridm/* หากบัญชีเปิดฟีเจอร์อารมณ์ ฟิลด์ emotion ของคำขอขายต่อ (openai/* · google/*) จะถูกละเว้น หากบัญชีปิดไว้
emotion:trueจะได้ 403FEATURE_DISABLEDไม่ว่าจะเป็นโมเดลใด - สตรีมมิง: ในการตอบกลับแบบสตรีม emotion จะรวมอยู่ในอีเวนต์ SSE message_done
API รูปภาพซาจู
สร้างงานศิลป์ AI ที่แสดงธาตุทั้งห้าและพลังงานของซาจู คืนค่าเป็นรูปแบบ PNG เข้ารหัส base64 คิดค่าบริการคงที่ ₩200
POST /api/v1/partners/v1/image
สร้างรูปภาพธาตุทั้งห้าของซาจูจากวันเดือนปีเกิด
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
year |
number | O | ปีเกิด (เช่น 1990) |
month |
number | O | เดือนเกิด (1-12) |
day |
number | O | วันเกิด (1-31) |
hour |
number | ชั่วโมงเกิด (0-23 ไม่บังคับ) | |
minute |
number | นาทีเกิด (0-59 ไม่บังคับ) | |
gender |
string | O | เพศ ("male" หรือ "female") |
style |
string | สไตล์ ("background", "icon", "portrait" ค่าเริ่มต้น: "background") — เปลี่ยนเฉพาะบรรยากาศ ขนาดเท่าเดิม |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/image \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female", "style": "portrait" }'
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"imageDataUri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
"costPoints": 200
}
}
ข้อควรระวัง
- ราคาคงที่: การสร้างรูปภาพทุกครั้งคิดค่าบริการ ₩200
- เวลาในการสร้าง: การสร้างรูปภาพใช้เวลา 20~30 วินาที ตั้งค่าไทม์เอาต์ให้เพียงพอ
- การเข้ารหัส Base64: imageDataUri ที่คืนมาเป็นรูปภาพ PNG ที่เข้ารหัส base64 ใช้กับแท็ก HTML
<img src="{imageDataUri}">ได้โดยตรง - สไตล์: background (ภาพพื้นหลัง) · icon (ไอคอนแบบมินิมอล) · portrait (ภาพประกอบบุคคล) เปลี่ยนเฉพาะบรรยากาศ ทุกสไตล์มีขนาดเท่ากัน (ค่าเริ่มต้นสี่เหลี่ยมจัตุรัส 1024×1024)
- ไทม์เอาต์: หากต้นทางไม่คืนรูปภาพภายใน 80 วินาที จะคืน 504
IMAGE_UPSTREAM_TIMEOUTและไม่คิดค่าบริการ ลองใหม่อีกครั้ง - ไม่ทราบเวลาเกิด: หากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือน้อยกว่าราคารูปภาพ 1 รูป |
| 504 | IMAGE_UPSTREAM_TIMEOUT | ไม่ได้รับรูปภาพภายใน 80 วินาที (ไม่คิดค่าบริการ) |
API สร้างรูปภาพ (ขายต่อโมเดล)
POST /api/v1/partners/v1/images/generations
เรียกโมเดล GPT-Image · Nano Banana ด้วยคีย์เดียวในรูปแบบเดียวกับ OpenAI Images API ราคาต่อรูปกำหนดไว้ตามโมเดล · ความละเอียด · คุณภาพ และจะหักตามจำนวนเงินในตารางตามเดิม (จำนวนรูปที่สร้าง × ราคาต่อรูป) ค่าโทเค็นขาเข้าของพรอมต์รวมอยู่ในราคาต่อรูปแล้ว ไม่คิดเพิ่มแยก
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
model | string | O | openai/gpt-image-2, openai/gpt-image-1-mini, google/nano-banana-pro, google/nano-banana, fal/nano-banana-pro, fal/nano-banana |
prompt | string | O | คำอธิบายรูปภาพที่จะสร้าง (สูงสุด 1,000 ตัวอักษร) หากเกินจะได้ 422 PROMPT_TOO_LONG (ตรวจหลังจองยอดคงเหลือ หากยอดไม่พอจะได้ 402 ก่อน) สตริงว่างจะได้ 400 EMPTY_PROMPT |
size | string | GPT-Image: 1024x1024 (ค่าเริ่มต้น) · 1024x1536 (แนวตั้ง) · 1536x1024 (แนวนอน) · auto (โมเดลเลือก — คิดค่าบริการตามราคาขนาดที่แพงที่สุดของคุณภาพนั้น) ค่าเดิม 256x256 · 512x512 จะสร้างและคิดค่าบริการเป็น 1024x1024, 1792x1024 เป็น 1536x1024, 1024x1792 เป็น 1024x1536 ใน Nano Banana ใช้เป็นสัดส่วนเท่านั้น — แนะนำให้ใช้ aspect_ratio | |
quality | string | เฉพาะ GPT-Image: low · medium (ค่าเริ่มต้น) · high ค่าเดิม standard=medium, hd=high ยังทำงานได้ตามเดิม หากส่ง low/medium/high ให้ Nano Banana จะได้ 400 | |
aspect_ratio | string | เฉพาะ Nano Banana: 21:9 · 16:9 · 3:2 · 4:3 · 5:4 · 1:1 (ค่าเริ่มต้น) · 4:5 · 3:4 · 2:3 · 9:16 สัดส่วนไม่มีผลต่อราคา มีลำดับความสำคัญเหนือ size | |
resolution | string | เฉพาะ Nano Banana: Nano Banana ใช้ได้เฉพาะ 1K ส่วน Nano Banana Pro ใช้ 1K (ค่าเริ่มต้น) · 2K · 4K อนุญาตเฉพาะ K ตัวพิมพ์ใหญ่ | |
n | number | จำนวนรูปที่สร้าง 1~4 (ค่าเริ่มต้น 1) โมเดล Google โดยตรงสร้างได้ 1 รูปต่อการเรียก และคิดค่าบริการ 1 รูป |
หากส่ง aspect_ratio · resolution ให้ GPT-Image หรือขอความละเอียดที่โมเดลไม่รองรับ จะถูกปฏิเสธด้วย 400 INVALID_PARAMETER และไม่คิดค่าบริการ
ข้อผิดพลาดอื่นๆ: MODEL_NOT_FOUND · INVALID_MODEL (400 โมเดลไม่มีอยู่), INVALID_PROMPT (400 ต้นทางปฏิเสธพรอมต์), UPSTREAM_ERROR, RATE_LIMITED (ปัจจุบัน HTTP 400 เนื้อหา status 429), INSUFFICIENT_BALANCE (402)
ราคาต่อรูป (₩ ไม่รวม VAT)
กำลังโหลดตารางราคา…
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/images/generations \
-H "X-Partner-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro",
"prompt": "A serene mountain landscape at sunset",
"aspect_ratio": "16:9",
"resolution": "2K"
}'
ตัวอย่างการตอบกลับ
{
"created": 1791452814,
"data": [ { "b64_json": "iVBORw0KGgo..." } ],
"costWon": 225,
"requestId": "..."
}
- GPT-Image · โมเดล Google โดยตรงคืนรูปภาพเป็น
b64_jsonส่วนโมเดล FAL คืนเป็นurl costWon= ราคาต่อรูป × จำนวนรูปที่สร้างจริง หากต้นทางไม่คืนรูปภาพเลยจะไม่คิดค่าบริการusage(จำนวนโทเค็น) ในการตอบกลับของ GPT-Image มีไว้เพื่ออ้างอิง ไม่ใช้ในการคิดราคา
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | MODEL_NOT_FOUND | โมเดลที่ไม่มีในตารางราคา |
| 400 | INVALID_MODEL | คำนำหน้าที่ไม่ใช่ openai/ · google/ · fal/ |
| 400 | INVALID_PARAMETER | ตัวเลือกที่โมเดลไม่รับ (aspect_ratio · resolution ใน GPT-Image, quality ใน Nano Banana, ความละเอียดที่ไม่รองรับ) |
| 400 | EMPTY_PROMPT | พรอมต์มีแต่ช่องว่าง |
| 400 | INVALID_PROMPT | โมเดลต้นทางปฏิเสธพรอมต์ |
| 400 | UPSTREAM_ERROR | ต้นทางผิดพลาดหรือได้รูปภาพ 0 รูป (ไม่คิดค่าบริการ) |
HTTP 400, เนื้อหา status 429 | RATE_LIMITED | ต้นทางจำกัดความเร็ว — ลองใหม่อีกครั้งในภายหลัง |
| 402 | INSUFFICIENT_BALANCE | ราคาต่อรูป × n มากกว่ายอดคงเหลือ |
| 422 | PROMPT_TOO_LONG | พรอมต์เกิน 1,000 ตัวอักษร |
การตอบกลับข้อผิดพลาดใช้รูปแบบ {"success": false, ...} เหมือน API อื่น (เฉพาะการตอบกลับที่สำเร็จที่ไม่ถูกห่อ)
การสร้างที่ใช้เวลานาน — การตอบกลับแบบอะซิงโครนัส (202 ไม่บังคับ)
คำขอความละเอียดสูง · หลายรูปอาจใช้เวลาเกิน 1 นาที หากใส่ Prefer: respond-async ในเฮดเดอร์คำขอ เมื่อผลลัพธ์ไม่พร้อมภายใน 60 วินาที ระบบจะไม่ค้างการเชื่อมต่อไว้ แต่คืน 202 Accepted พร้อม ID งาน และการสร้างจะดำเนินต่อบนเซิร์ฟเวอร์ได้สูงสุด 240 วินาที หากเสร็จภายใน 60 วินาทีจะได้การตอบกลับ 200 เหมือนเดิมทุกอย่าง หากไม่ส่งเฮดเดอร์จะเหมือนเดิมทุกประการ (หากไม่เสร็จภายใน 80 วินาทีจะได้ 504 IMAGE_UPSTREAM_TIMEOUT ไม่คิดค่าบริการ) — ส่งเฮดเดอร์เฉพาะไคลเอนต์ที่พร้อมจัดการ 202
curl -X POST https://api.hrum.ai/api/v1/partners/v1/images/generations \
-H "X-Partner-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: respond-async" \
-d '{"model": "google/nano-banana-pro", "prompt": "...", "resolution": "4K"}'
HTTP/1.1 202 Accepted
Location: /api/v1/partners/v1/jobs/imgjob_3f2a...
Retry-After: 5
Preference-Applied: respond-async
{
"id": "imgjob_3f2a...",
"object": "image.job",
"status": "pending",
"pollUrl": "/api/v1/partners/v1/jobs/imgjob_3f2a...",
"retryAfter": 5,
"createdAt": "2026-10-12T03:00:00.000Z",
"expiresAt": "2026-10-13T03:00:00.000Z"
}
GET /api/v1/partners/v1/jobs/{id}
ดึงข้อมูลด้วยคีย์ API เดียวกัน (X-Partner-Api-Key) ทุก Retry-After วินาที การดึงข้อมูลฟรีและไม่นับในโควตาคำขอรายวัน แต่จำกัด 1 ครั้งต่อ 2 วินาทีต่อคีย์ API หากเรียกถี่กว่านั้นจะได้ 429 IMAGE_JOB_POLL_RATE_LIMITED พร้อม Retry-After (วินาที) การตอบกลับเป็น HTTP 200 และแยกสถานะด้วย status ในเนื้อหา
| status | เนื้อหา |
|---|---|
pending | ยังสร้างอยู่ — ดึงข้อมูลใหม่หลังเฮดเดอร์ Retry-After · retryAfter |
succeeded | result = การตอบกลับ 200 ที่การเรียกแบบซิงโครนัสจะคืนให้ตามเดิม (data · costWon · requestId) |
failed | error = เนื้อหาข้อผิดพลาดที่การเรียกแบบซิงโครนัสจะคืนให้ตามเดิม (statusCode · code · message) — ไม่คิดค่าบริการ |
- การคิดค่าบริการ: หักเพียงครั้งเดียวเมื่อผลลัพธ์พร้อม ระหว่างรอจะจองยอดคงเหลือไว้เท่ากับยอดที่คาดไว้ หากล้มเหลว · หมดเวลา การจองจะถูกปลดและไม่คิดค่าบริการ ดึงข้อมูลหลายครั้งก็ไม่คิดค่าบริการซ้ำ
- การเก็บรักษา: ผลลัพธ์ · ข้อผิดพลาดดึงข้อมูลได้ภายใน 24 ชั่วโมงหลังสร้างงาน หลังจากนั้นจะถูกลบ (ต่อจากนั้นเป็น 404) หากรูปภาพเป็น
b64_jsonการตอบกลับของการดึงข้อมูลก็ใหญ่ตามนั้น (รูปละหลาย MB) — ได้รับแล้วให้เก็บทันที หากผลลัพธ์ทั้งหมดเกิน 16MB จะไม่เก็บรักษาและถือว่าล้มเหลวด้วยIMAGE_JOB_RESULT_TOO_LARGE(ไม่คิดค่าบริการ) — ลดจำนวนรูป (n) หรือความละเอียด - ID งานของพาร์ทเนอร์อื่น ID ที่ไม่มีอยู่ และ ID ที่เลยระยะเก็บรักษาแล้ว ล้วนได้ 404
IMAGE_JOB_NOT_FOUNDเหมือนกัน
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 202 | — | คำขอ Prefer: respond-async ไม่เสร็จภายใน 60 วินาที — ดึงข้อมูลด้วย ID งานข้างต้น |
| 404 | IMAGE_JOB_NOT_FOUND | ID งานที่ไม่มีอยู่ · หมดอายุ · ของพาร์ทเนอร์อื่น |
| 429 | IMAGE_JOB_POLL_RATE_LIMITED | ดึงข้อมูลซ้ำด้วยคีย์ API เดียวกันภายใน 2 วินาที — ลองหลัง Retry-After วินาที |
error.statusCode 504 | IMAGE_UPSTREAM_TIMEOUT | ไม่ได้รับรูปภาพภายใน 240 วินาที (ไม่คิดค่าบริการ) |
error.statusCode 413 | IMAGE_JOB_RESULT_TOO_LARGE | ผลลัพธ์เกิน 16MB (ไม่คิดค่าบริการ) |
error.statusCode 503 | IMAGE_JOB_INTERRUPTED | งานถูกตัดเพราะเซิร์ฟเวอร์รีสตาร์ต (ไม่คิดค่าบริการ) — ส่งคำขอใหม่ |
error.statusCode 402 | — | ยอดคงเหลือไม่พอเมื่อผลลัพธ์ออกมา (ไม่คิดค่าบริการ) |
API ปฏิทินหมื่นปี
POST /api/v1/partners/v1/manseryeok
รวมอัตลักษณ์ซาจู — ฟิลด์ identity ท้ายการตอบกลับมีสามภัย · ดาวพิเศษ · ช่องว่าง · การหยั่งราก · ความแข็ง-อ่อนตามฤดู · ไทม์ไลน์วัยจร 10 ปี/ดวงรายปี · MBTI ซาจู อยู่ด้วย (ไม่มีค่าบริการเพิ่ม หากคำนวณล้มเหลวจะเป็น null)
คำนวณก้านฟ้า · กิ่งดิน · ฮันจา · ธาตุทั้งห้า · สิบเทพ · ก้านแฝง · นาบึม · 12 วัฏจักรชีวิต · ดาวพิเศษของผังดวง 4 เสา (ปี · เดือน · วัน · ยาม) ด้วยการคำนวณที่แม่นยำตามจุดเปลี่ยนฤดู ให้การตีความซาจูที่สมบูรณ์ตั้งแต่ การวิเคราะห์ผังดวง (ธาตุช่วย · เสริม-กด · ธาตุช่วยปรับฤดู · ความแข็ง-อ่อนของดวง · ความใส-ขุ่น · ธาตุเชื่อม · โรค-ยา · ตัวแปรธาตุทั้งห้า) → วัยจร 10 ปี 10 ช่วง (รวมวัยจรปัจจุบัน · การรวม · ปะทะ · ลงโทษ · ทำร้ายของก้าน-กิ่ง) → ดวงรายปี 5 ปี (ระดับ · ความสัมพันธ์ · การตีความรายปี) → รูปแบบดวง · การตีความโดยละเอียด → ทฤษฎีก้านฟ้า 10 ตัว · สภาพตามฤดู · ช่องว่าง · อักษรแฝง · การรวมลอย · ลาภซ่อน ผ่านฟิลด์พื้นฐานระดับบนสุด 30 ฟิลด์ + ฟิลด์ตัวเลือก (รวมฟิลด์ย่อยกว่า 200 ฟิลด์) หากไม่ทราบเวลาเกิด จะมีเพียงเสายาม (wonkuk.hour) และ trueSolarTime ที่ต้องใช้เวลาจริงเท่านั้นที่เป็น null ส่วนฟิลด์วิเคราะห์อย่างธาตุช่วย · รูปแบบดวง · ความแข็ง-อ่อนของดวง ยังให้ค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) ตามเดิม (birthHour.basis: "three_pillars")
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
year |
number | O | ปีเกิด (เช่น 1990) |
month |
number | O | เดือนเกิด (1-12) |
day |
number | O | วันเกิด (1-31) |
hour |
number | ชั่วโมงเกิด (0-23) หากละไว้ จะตัดเฉพาะเสายามออกจากการตอบกลับ (wonkuk.hour: null) และฟิลด์วิเคราะห์อย่างธาตุช่วย · รูปแบบดวง · ความแข็ง-อ่อนของดวง · ดวงรายปี จะให้ค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) หากส่ง minute โดยไม่มี hour จะถูกละเว้น |
|
minute |
number | นาทีเกิด (0-59 ค่าเริ่มต้น: 0) | |
timezone |
string | O | เขตเวลา (เช่น Asia/Seoul) จำเป็น — หากละไว้จะได้ 400 ใช้กำหนดเส้นเมริเดียนมาตรฐานเมื่อส่งพิกัด หากส่ง astrology: true ไม่ว่าจะมีพิกัดหรือไม่ จะอ่านเวลาเกิดของ natalChart เป็นเวลาที่ใช้จริงในเขตเวลานี้ ณ เวลานั้น (รวมเวลาออมแสง) หากเป็นชื่อที่ไม่รู้จัก จะคำนวณด้วยเขตเวลาเริ่มต้นและการตอบกลับจะมี warnings (UNKNOWN_TIMEZONE) แนบมา |
gender |
string | O | เพศ ("male" หรือ "female" จำเป็น) |
name |
string | ชื่อ-นามสกุล (ไม่บังคับ) | |
astrology |
boolean | ไม่บังคับ | หากเป็น true การตอบกลับจะแนบ natalChart (ราศีของดวงอาทิตย์ · ดวงจันทร์ · ดาวพุธ~ดาวเสาร์) ลัคนาจะออกมาเฉพาะเมื่อส่งเวลาเกิดและตำแหน่ง (birthLatitude · birthLongitude หรือ country) มาด้วย หากส่งโดยไม่มีตำแหน่ง ราศีจะคำนวณตามเวลาเที่ยงวัน — หากต้องการรายละเอียด เช่น ช่วงประมาณการลัคนา ให้ใช้ API ผังดวงกำเนิด |
glossary |
boolean | ไม่บังคับ | หากเป็น true จะแนบคำอธิบาย (title · short · body ในภาษา lang) ของศัพท์ที่ปรากฏในผังนี้ (ฮันจาของก้าน-กิ่ง · สิบเทพ · 12 วัฏจักรชีวิต · นาบึม · ดาวพิเศษ · ก้านแฝง · ปะทะ-ลงโทษ · ความสัมพันธ์ของกิ่งดิน · รูปแบบดวง · ช่องว่าง · สามภัย) ไว้ใน glossary ของการตอบกลับ ไม่มีค่าบริการเพิ่ม ศัพท์ที่ไม่มีคำอธิบายในภาษาที่ขอจะมาเป็นภาษาเกาหลี และรายการนั้นจะมี "fallbackLanguage": "ko" แนบมา คีย์ของ glossary เป็นรหัสฮันกึล/ฮันจาไม่ว่า lang จะเป็นอะไร |
lang |
string | ภาษาของสตริงการตีความ: ko (ค่าเริ่มต้น ไม่แปล) · en · ja · th ใช้ตารางแปลเดียวกับหน้าจอปฏิทินหมื่นปีของแอป INTA |
|
calendar · isLeapMonth |
string · boolean | หากเป็น "lunar" จะรับ year · month · day เป็นปฏิทินจันทรคติแล้วแปลงเป็นสุริยคติเพื่อคำนวณ (ค่าเริ่มต้น "solar") isLeapMonth: true คือเดือนอธิกมาส — หากปีนั้นไม่มีเดือนอธิกมาสนั้นจะได้ 400 INVALID_LUNAR_DATE (ตั้งแต่ 2026-10-12 ไม่คิดค่าบริการ) ปฏิทินจันทรคติอิงสถาบันดาราศาสตร์และอวกาศเกาหลี (KASI) และรับช่วงจันทรคติ 1900-01-01 ~ 2050-11-30 |
|
birthLatitude · birthLongitude |
number | พิกัดสถานที่เกิด (ต้องส่งทั้งสองค่า) ใช้ลองจิจูดปรับเวลาสุริยะจริง เส้นเมริเดียนมาตรฐานกำหนดจากเวลามาตรฐานของ timezone (ไม่รวมเวลาออมแสง) ส่วน natalChart (ราศี) วาดจากเวลาที่ใช้จริง ณ เวลาเกิด (รวมเวลาออมแสง) ไม่ใช่เวลามาตรฐาน |
|
country |
string | รหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับด้วยลองจิจูดตัวแทนของประเทศนั้น (ประเทศอื่นไม่มีการปรับ) |
|
zaSiRule |
string | เสาวันของยามจื่อ (หลัง 23 นาฬิกา): "traditional" (ค่าเริ่มต้น เสาวันของวันถัดไป) · "yajaSi" (ยามจื่อกลางคืน เสาวันของวันนั้น · หลังปรับตามตำแหน่ง ก้านฟ้าของเสายามช่วง 23 นาฬิกาอิงก้านวันเกิดของวันถัดไป ตั้งแต่ 2026-10-20) |
|
birthTimePrecision |
string | exact · approximate · estimated · unknown การปรับตามตำแหน่งใช้เฉพาะเมื่อเป็น exact หากละไว้แต่ส่งพิกัดหรือ country จะถือเป็น exact เวลาเกิดในช่วงเวลาออมแสงของเกาหลี (1948~51 · 1955~60 · 1987~88) จะลบ 1 ชั่วโมงแล้วอ่านเป็นเวลามาตรฐาน ไม่ว่าค่านี้หรือตำแหน่งจะเป็นอย่างไร (2026-10-16 เหมือนแอป INTA) หาก country ไม่ใช่ KR หรือ timezone ไม่ใช่โซล จะไม่ลบเวลาออมแสงของเกาหลี |
ฟิลด์ในการตอบกลับ (พื้นฐาน 30 ฟิลด์ + ฟิลด์ตัวเลือก)
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
wonkuk |
object | ผังดวง (4 เสา) year, month, day, hour (hour เป็น null เมื่อไม่ทราบเวลาเกิด) แต่ละรายการดูโครงสร้าง PillarFull |
trueSolarTime |
object|null | ผลการปรับเวลาสุริยะจริง (ลองจิจูด) มีค่าเฉพาะเมื่อส่งพิกัด (birthLatitude · birthLongitude) หรือ country (KR · JP · TH) และ birthTimePrecision เป็น exact (หากส่งตำแหน่ง ค่าเริ่มต้นคือ exact) นอกนั้นเป็น null ฟิลด์: original · corrected (ISO 8601), originalLocal · correctedLocal (HH:MM), longitudeCorrection · equationOfTime · totalCorrectionMinutes (นาที), dayShift, dstApplied, basis ('coords' หรือ 'country') เป็น null เมื่อไม่ทราบเวลาเกิด |
ohaengBalance |
object | สมดุลธาตุทั้งห้า { 목: int, 화: int, 토: int, 금: int, 수: int } (ไม้ ไฟ ดิน ทอง น้ำ) |
yongshin |
string | ธาตุช่วยสุดท้าย — ผลการตัดสินด้วย 5 หลัก (ธาตุครองเด่น · ปรับฤดู · เสริม-กด · ธาตุเชื่อม · โรค-ยา) ตั้งแต่ 2026-10-08 เป็นค่าเดียวกับ yongshinDetail.primary (เช่น "수" = น้ำ) |
johuYongshin |
string|null | ธาตุช่วยปรับฤดู (แยกจาก "ธาตุช่วยแบบเสริม-กด") |
eokbuYongshin |
string | ธาตุช่วยแบบเสริม-กด (ธาตุช่วยที่ได้จากการชั่งดวงแข็ง · ดวงอ่อน) อาจต่างจากธาตุช่วยสุดท้าย (yongshin) |
yongshinDetail |
object |
ผลของเอนจินธาตุช่วยฉบับสมบูรณ์ ตัดสินตามลำดับความสำคัญ 5 หลัก (ธาตุครองเด่น → ปรับฤดู → เสริม-กด → ธาตุเชื่อม → โรค-ยา)
ประกอบด้วย method (หลักที่เลือก), primary (ธาตุช่วย), secondary (ธาตุช่วยรอง),
reasoning (อาร์เรย์ประโยคเหตุผลการตัดสิน), shin (5 ระดับ: ธาตุช่วย · ธาตุยินดี · ธาตุต้องห้าม · ธาตุศัตรู · ธาตุว่าง),
favorable_sipsin/unfavorable_sipsin (สิบเทพที่เป็นคุณ · เป็นโทษ),
element_states (จำนวน · ขาด-เกิน · คุณ-โทษ ของแต่ละธาตุ)
yongshin ข้างต้นเป็นค่าเดียวกับ primary ของเอนจินนี้ (ตั้งแต่ 2026-10-08)
หากการตีความต้องใช้ถึงเหตุผลการตัดสิน ให้ใช้ฟิลด์นี้
แม้ไม่ทราบเวลาเกิดก็ให้ค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร)
|
ilganSummary |
string | ทฤษฎีก้านวันเกิด 10 ตัว ตัวอย่าง: "壬水 — 큰 바다의 기운. 지혜롭고 포용력이 넓어요." (ใช้เฉพาะก้านวันเกิด จึงให้ค่าเสมอไม่ว่าจะทราบเวลาเกิดหรือไม่) |
daeun |
array | วัยจร 10 ปี 10 ช่วง (10 รายการเสมอ) แต่ละรายการมีอายุเริ่มต้น ก้านฟ้า · กิ่งดิน ธาตุทั้งห้า สิบเทพ ดาวพิเศษ isCurrent (เป็นวัยจรปัจจุบันหรือไม่) แต่ละช่วงคือ startAge ขึ้นไปถึงต่ำกว่า endAge ดังนั้น endAge ของช่วงก่อนจะเท่ากับ startAge ของช่วงถัดไป หากไม่มี gender หรือเป็น "other" จะเป็นอาร์เรย์ว่าง ดูโครงสร้าง DaeunPeriod |
seun |
array | ดวงรายปี 5 ปี — มีปีนี้อยู่ตรงกลาง ก่อนและหลังอย่างละ 2 ปี (ปีนี้ −2 ปี ~ +2 ปี เรียงปีจากน้อยไปมาก) เฉพาะรายการของปีนี้ที่เป็น isCurrent: true แต่ละรายการมีปี ก้านฟ้า · กิ่งดิน ธาตุทั้งห้า grade (good/caution/excellent/neutral) ความสัมพันธ์ (ทำร้าย/รวมหก/ลงโทษ ฯลฯ) และสรุป ดูโครงสร้าง SeunYear |
branchRelations |
array | ความสัมพันธ์ของกิ่งดิน รายการคู่กิ่งดินที่มีการปะทะ · ลงโทษ · รวม ระหว่างเสาปี เดือน วัน ยาม แต่ละรายการมี type ('沖(충)'/'刑(형)'/'半合(반합)' ฯลฯ), pillars, description (เช่น "丑未沖 (축미충)") |
gongmang |
array | กิ่งดินช่องว่าง 2 ตัว — ช่องว่างในรอบสิบ (sunjung gongmang) ตามเสาวัน (2 ตัวเสมอ ไม่ว่าผังดวงจะมีกิ่งดินนั้นหรือไม่) ตัวอย่าง: ["술", "해"] |
cheonEulGwiIn |
array | รายการกิ่งดินในผังดวงที่เป็นผู้อุปถัมภ์สวรรค์ (cheoneul gwiin) ใช้เกณฑ์เดียวกับกิ่งดินของเสาที่มี "천을귀인" ใน minorSinsal ของแต่ละเสา หากไม่มีเสาที่ตรงจะเป็น [] ตัวอย่าง: ["묘"] |
wolryeong |
string | กิ่งดินประจำเดือน (wolryeong — กิ่งดินที่ครองเดือนปัจจุบันตามจุดเปลี่ยนฤดู) ตัวอย่าง: "축" |
daeunNumber |
number | เลขวัยจร — อายุที่วัยจรแรกเริ่มต้น (daeun[0].startAge เช่น 3) ไม่ใช่ลำดับของวัยจรปัจจุบัน — วัยจรปัจจุบันให้หาจาก daeun[].isCurrent |
daeunDirection |
string | ทิศทางวัยจร "순행" (เดินหน้า) หรือ "역행" (ถอยหลัง) |
gyeokguk |
object|null | การตัดสินรูปแบบดวง name ('정관격' ฯลฯ) · summary ('질서·명예·합리') แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
gyeokgukDetail |
object|null | การตีความรูปแบบดวงโดยละเอียด primary · source · trigger · interpretation (core/career/personality/challenge) แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
cheonganDetail |
object|null | รายละเอียดทฤษฎีก้านฟ้า 10 ตัว ilgan · hanja · archetype · characteristics · seasonal · relations แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
hapChungReport |
object|null | รายงานรวมการลงโทษ · ปะทะ · ประชุม · รวมของก้านฟ้า · กิ่งดิน สถานะการรวม/ปะทะที่คงอยู่ในผังดวง และความสัมพันธ์ที่เกิดใหม่ในวัยจร/ดวงรายปี แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
heojaReport |
object|null | รายงานรวมอักษรแฝง hapHeo · jaHeo · bihap · bihapEmergence · heojaGyeok · amrok แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) แต่ heojaGyeok (รูปแบบอักษรแฝง) ต้องมีกิ่งดินของยามจริงจึงจะเกิดขึ้น จึงว่างไว้ |
gongmangDetail |
object|null | รายงานช่องว่างโดยละเอียด ช่องว่างตามเสาปี · เสาวัน ช่องว่างของธาตุทั้งห้าหรือไม่ ฯลฯ |
ohaengByeonsuHits |
array | ดึงตัวแปรธาตุทั้งห้าอัตโนมัติ ตัวอย่างการใช้สูตรรุ่งเรือง · ข่ม · ถ่ายทอด แต่ละรายการมี key · subject (ธาตุทั้งห้า) · target · formula_idiom · description · category |
strength |
object|null | คะแนน · ระดับความแข็ง-อ่อนของดวง dayMaster · score (-100~+100) · result ('신강' ดวงแข็ง/'신약' ดวงอ่อน) · level · breakdown (ฤดู · การเกื้อหนุน · การข่ม-ถ่าย · ก้านแฝง · การหยั่งราก) แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
jeongtak |
object|null | การตัดสินความใส-ขุ่น verdict ('정' ใส/'탁' ขุ่น) · reasons · severity แม้ไม่ทราบเวลาเกิดก็เป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) |
tonggwan |
object|null | มีธาตุเชื่อมหรือไม่ ผลจากตรรกะแบบผสม |
byeongyak |
object|null | มีโรค-ยาหรือไม่ ผลจากตรรกะแบบผสม |
natalChart |
object|null | ผังดวงกำเนิด (Natal Chart) ของโหราศาสตร์ตะวันตก (ตัวเลือก เฉพาะเมื่อ astrology=true) ราศีของ 7 ดาว ดวงอาทิตย์ · ดวงจันทร์ · ดาวพุธ~ดาวเสาร์ และลัคนา (เมื่อส่งตำแหน่ง) |
countryCodeUsed |
string|null | รหัสประเทศที่ใช้คำนวณการตอบกลับนี้ (เมื่อส่ง country) หากไม่มีเป็น null |
identity |
object|null | รวมเสมอ (ตั้งแต่ 2026-10-10) อัตลักษณ์ซาจู — rooting_hints (การหยั่งราก) · season_strength_hint (ความแข็ง-อ่อนตามฤดู) · sinsal_list (ดาวพิเศษ) · gongmang (ช่องว่าง) · samjae (สามภัย) · timeline (ไทม์ไลน์วัยจร 10 ปี/ดวงรายปี) · mbti_inference (MBTI ซาจู) · coherence หากคำนวณล้มเหลวเป็น null ดูอัตลักษณ์ซาจู |
ohaengDeficient |
array of string | รวมเสมอ (ตั้งแต่ 2026-10-10) รายการธาตุที่มีจำนวนเป็น 0 ใน ohaengBalance (หากไม่มีเป็น []) หาก lang ไม่ใช่ ko จะมาเป็นชื่อที่แปลแล้ว (คีย์ของ ohaengBalance เป็นฮันกึลตามเดิม) |
glossary |
object | ตัวเลือก เฉพาะเมื่อ glossary=true คีย์ศัพท์ → { title, short, body, fallbackLanguage? } |
lunarInput |
object | ตัวเลือก เฉพาะเมื่อ calendar: "lunar" รายละเอียดการแปลงจันทรคติ→สุริยคติ |
birthHour |
object | ตัวเลือก เฉพาะเมื่อละ hour เมตาของกรณีไม่ทราบเวลาเกิด (ดูข้อควรระวังด้านล่าง) |
โครงสร้าง PillarFull (ฟิลด์ย่อยของแต่ละเสา)
ฟิลด์ที่ wonkuk.year · wonkuk.month · wonkuk.day · wonkuk.hour ในการตอบกลับแต่ละตัวมี:
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
stem |
string | ก้านฟ้า "갑", "을", "병", "정", "무", "기", "경", "신", "임", "계" |
branch |
string | กิ่งดิน "자", "축", "인", "묘", "진", "사", "오", "미", "신", "유", "술", "해" |
stemHanja |
string | ฮันจาของก้านฟ้า "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" |
branchHanja |
string | ฮันจาของกิ่งดิน "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" |
ohaeng |
string | ธาตุทั้งห้า หนึ่งใน "목", "화", "토", "금", "수" (ไม้ ไฟ ดิน ทอง น้ำ) |
stemSipsin |
string | สิบเทพของก้านฟ้า (เทียบกับก้านวันเกิด) หนึ่งใน "정관", "편관", "정재", "편재", "식신", "상관", "정인", "편인", "비견", "겁재" |
branchSipsin |
string | สิบเทพของกิ่งดิน (เทียบกับก้านวันเกิด) 10 ค่าเดียวกับสิบเทพของก้านฟ้า |
jijanggan |
array of string | ก้านแฝง (ก้านฟ้าที่ซ่อนอยู่ในกิ่งดิน) ตัวอย่าง: ["갑", "을", "목"] หรือ ["갑", "을"] ฯลฯ |
chunghyung |
array of string | ปะทะ-ลงโทษ (ความสัมพันธ์กับเสาอื่น) "沖(충)" · "刑(형)" ฯลฯ ตัวอย่าง: ["沖(충)", "刑(형)"] |
hapPosition |
array of string | ตำแหน่งการรวม (ความสัมพันธ์กับเสาอื่น) "半合(반합)" · "육합" ฯลฯ ตัวอย่าง: ["半合(반합)"] |
ungSung |
string | 12 วัฏจักรชีวิต หนึ่งใน "장생", "목욕", "관대", "건록", "제왕", "쇠", "병", "사", "묘", "절", "태", "양" |
ungSungSub |
string (ไม่บังคับ) | ข้อมูลเสริมของ 12 วัฏจักรชีวิต (ฟิลด์ไม่บังคับ) |
napEum |
string | ธาตุนาบึม ตัวอย่าง: "성두토", "간하수", "검봉금" ฯลฯ |
majorSinsal |
array of string | ดาวพิเศษหลัก ตัวอย่าง: ["장성살"], ["지살"] ฯลฯ |
minorSinsal |
array of string | ดาวพิเศษรอง ตัวอย่าง: ["천을귀인", "귀문관살", "원진살", "현침살", "육해살"] ฯลฯ |
โครงสร้าง DaeunPeriod (แต่ละช่วงของวัยจร 10 ปี)
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
startAge |
number | อายุเริ่มต้น (ช่วงนี้เริ่มจากอายุนี้) |
endAge |
number | อายุสิ้นสุด — ไม่รวมอายุนี้ เป็นค่าเดียวกับ startAge ของช่วงถัดไป (เช่น 3~13, 13~23) |
stem |
string | ก้านฟ้า |
branch |
string | กิ่งดิน |
stemHanja |
string | ฮันจาของก้านฟ้า |
branchHanja |
string | ฮันจาของกิ่งดิน |
ohaeng |
string | ธาตุทั้งห้า |
isCurrent |
boolean | เป็นวัยจรปัจจุบันหรือไม่ (true คือกำลังดำเนินอยู่ตอนนี้) |
stemSipsin |
string | สิบเทพของก้านฟ้า |
branchSipsin |
string | สิบเทพของกิ่งดิน |
sinsal |
array of string | อาร์เรย์ดาวพิเศษ |
โครงสร้าง SeunYear (แต่ละปีของดวงรายปี)
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
year |
number | ปีคริสต์ศักราช |
stem |
string | ก้านฟ้า |
branch |
string | กิ่งดิน |
stemHanja |
string | ฮันจาของก้านฟ้า |
branchHanja |
string | ฮันจาของกิ่งดิน |
ohaeng |
string | ธาตุทั้งห้า |
isCurrent |
boolean | เป็นดวงรายปีปัจจุบันหรือไม่ |
grade |
string | ระดับ "good" (ราบรื่น), "excellent" (ดีมาก), "caution" (ระมัดระวัง), "neutral" (ไม่มีการเปลี่ยนแปลง) |
relations |
array | ความสัมพันธ์ของก้าน-กิ่ง แต่ละรายการมี type (ทำร้าย/รวมหก/ลงโทษ ฯลฯ) · target (เสาปี/เสาเดือน ฯลฯ) · description |
summary |
string | สรุปการตีความรายปี ตัวอย่าง: "전체적으로 순조로운 흐름이 예상돼요." |
sinsal |
array of string | อาร์เรย์ดาวพิเศษ |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/manseryeok \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"year": 2000, "month": 1, "day": 15, "hour": 14, "minute": 30,
"gender": "male", "calendar": "solar", "timezone": "Asia/Seoul"
}'
ตัวอย่างการตอบกลับ (ตัดตอน: 2000-01-15 14:30 เพศชาย)
{
"success": true,
"data": {
"wonkuk": {
"year": {
"stem": "기", "branch": "묘", "stemHanja": "己", "branchHanja": "卯",
"ohaeng": "토", "stemSipsin": "정관", "branchSipsin": "상관",
"jijanggan": ["갑", "을"], "chunghyung": [], "hapPosition": ["半合(반합)"],
"ungSung": "사", "napEum": "성두토",
"majorSinsal": ["장성살"],
"minorSinsal": ["천을귀인", "귀문관살", "원진살", "현침살", "육해살"]
},
"month": { ... },
"day": { ... },
"hour": { ... }
},
"trueSolarTime": null,
"ohaengBalance": { "목": 1, "화": 2, "토": 3, "금": 1, "수": 1 },
"yongshin": "수",
"johuYongshin": "화",
"yongshinDetail": {
"method": "억부",
"primary": "수",
"secondary": ["금"],
"reasoning": ["일간 임(수) 신약", "신약 + root 있음(8) → 비겁(수)"],
"shin": { "yongshin": "수", "huishin": "금", "gishin": "토", "gushin": "화", "hanshin": "목" },
"favorable_sipsin": ["편인", "정인", "비견", "겁재"],
"unfavorable_sipsin": ["편관", "정관", "편재", "정재", "식신", "상관"],
"element_states": { "목": { "count": 1, "state": "lack", "effect": "neutral" }, "...": "5오행" }
},
"eokbuYongshin": "수",
"ilganSummary": "壬水 — 큰 바다의 기운. 지혜롭고 포용력이 넓어요.",
"daeun": [
{
"startAge": 3, "endAge": 13,
"stem": "병", "branch": "자", "stemHanja": "丙", "branchHanja": "子",
"ohaeng": "화", "isCurrent": false,
"stemSipsin": "편재", "branchSipsin": "겁재",
"sinsal": ["년살", "장성살"]
},
{
"startAge": 13, "endAge": 23,
"stem": "을", "branch": "해", "stemHanja": "乙", "branchHanja": "亥",
"ohaeng": "목", "isCurrent": false,
"stemSipsin": "상관", "branchSipsin": "비견",
"sinsal": ["지살", "망신살"]
},
{
"startAge": 23, "endAge": 33,
"stem": "갑", "branch": "술", "stemHanja": "甲", "branchHanja": "戌",
"ohaeng": "목", "isCurrent": true,
"stemSipsin": "식신", "branchSipsin": "편관",
"sinsal": ["천살", "월살"]
}
// … cycles 4–10 (startAge 33–93) omitted — the actual response has 10
],
"seun": [
// 2024 and 2025 entries omitted
{
"year": 2026, "stem": "병", "branch": "오", "stemHanja": "丙", "branchHanja": "午",
"ohaeng": "화", "isCurrent": true, "grade": "good",
"relations": [
{ "type": "해", "target": "월주", "description": "오-축 해" },
{ "type": "육합", "target": "시주", "description": "오-미 육합" }
],
"summary": "전체적으로 순조로운 흐름이 예상돼요. (해, 육합 작용)",
"sinsal": ["육해살", "재살"]
}
// 2027 and 2028 entries omitted — the actual response has 5: two years either side of this year
],
"branchRelations": [
{ "type": "沖(충)", "pillars": ["축", "미"], "description": "丑未沖 (축미충)" },
{ "type": "半合(반합)", "pillars": ["묘", "미"], "description": "卯未合 (묘미합)" }
],
"gongmang": ["술", "해"],
"cheonEulGwiIn": ["묘"],
"wolryeong": "축",
"daeunNumber": 3,
"daeunDirection": "역행",
"gyeokguk": {
"name": "정관격",
"summary": "질서·명예·합리"
},
"gyeokgukDetail": { ... },
"cheonganDetail": { ... },
"hapChungReport": { ... },
"heojaReport": { ... },
"gongmangDetail": { ... },
"ohaengByeonsuHits": [
{
"key": "to_wang_deuk_mok",
"subject": "土", "target": "木",
"formula_idiom": "방능소통(方能疏通)",
"description": "토가 왕성한데 목을 얻으면 소통이 된다",
"category": "wang_geuk_sunwha"
},
{
"key": "gang_to_deuk_geum",
"subject": "土", "target": "金",
"formula_idiom": "방제기해(方制其害)",
"description": "강한 토가 금을 얻으면 그 피해를 막는다",
"category": "gang_seolgi_sunwha"
}
],
"strength": {
"dayMaster": "임",
"score": -66,
"result": "신약",
"level": "중약",
"breakdown": { "season": -30, "support": 8, "control": -38, "hidden": -9, "root": 8 },
"root": { "rooted": true, "rootScore": 8 }
},
"jeongtak": {
"verdict": "탁",
"reasons": ["파괴 십신 2개 감지", "용신 금 생 ✓", "일주 신약"],
"severity": "극탁"
},
"tonggwan": { ... },
"byeongyak": { ... },
"countryCodeUsed": null,
"identity": {
"rooting_hints": { ... }, "season_strength_hint": { ... }, "sinsal_list": [ ... ],
"gongmang": { ... }, "samjae": { ... }, "timeline": { ... },
"mbti_inference": { ... }, "coherence": { ... }
},
"ohaengDeficient": []
}
}
ตัวอย่างนี้เป็นผลที่เรียกในปี 2026 ปีของ daeun[].isCurrent · seun จึงเปลี่ยนตามปีที่เรียก บรรทัด { ... } และ // คือเครื่องหมายละ ตัวอย่างนี้เป็นคำขอที่ไม่ได้ส่งตำแหน่ง trueSolarTime จึงเป็น null หากเพิ่ม "country": "KR" (หรือพิกัด) ในคำขอเดียวกัน trueSolarTime จะมีผลการปรับ ("basis": "country") และ countryCodeUsed จะเป็น "KR" รูปแบบผลการปรับดูได้จากตัวอย่างอินพุตจันทรคติในข้อควรระวังด้านล่าง
ข้อควรระวัง
- การตอบกลับที่ซับซ้อน: การตอบกลับของปฏิทินหมื่นปีไม่ได้มีแค่ผังดวง แต่มีข้อมูลละเอียดอย่างวัยจร 10 ปี ดวงรายปี รูปแบบดวง ดาวพิเศษ ฯลฯ เลือกใช้เฉพาะฟิลด์ที่ต้องการ
- ฟิลด์ไม่บังคับ — ข้อตกลงเมื่อไม่ทราบเวลาเกิด: ละ
hour·minuteได้ หากละhourจะไม่สมมติเป็นเที่ยงวัน แต่ตัดเสายามออก การตอบกลับจะต่างไปดังนี้wonkuk.hour=null,trueSolarTime=nullohaengBalance= คำนวณใหม่ตาม 3 เสา ปี · เดือน · วัน (ก้านฟ้า+กิ่งดิน 6 อักษร)branchRelations·cheonEulGwiIn= คงไว้เฉพาะรายการที่เกิดขึ้นได้จากกิ่งดินของ 3 เสา- เพิ่ม
birthHourระดับบนสุด:{ known: false, hourPillar: null, basis: "three_pillars", excludedFields: [], note }ฟิลด์วิเคราะห์ (yongshin·strength·gyeokguk·hapChungReport·ilganSummary·seunฯลฯ) ไม่ถูกลบ และส่งเป็นค่าที่คำนวณจาก 3 เสา ปี · เดือน · วัน (6 อักษร) (เกณฑ์ที่ขึ้นกับจำนวนอักษรก็แปลงเป็นเกณฑ์ 6 อักษร) ไม่ใช่ค่าอ้างอิงตามเที่ยงวัน แต่เป็นค่าที่ได้จาก 3 เสาเท่านั้น - ใช้
birthHour.knownในการตัดสินว่าไม่ทราบเวลาเกิดหรือไม่ — อย่าตัดสินด้วยexcludedFields.lengthอาร์เรย์นี้ว่างเสมอแล้ว และคงไว้เพื่อความเข้ากันได้กับไคลเอนต์รุ่นเก่าเท่านั้น - หากส่ง
minuteโดยไม่มีhourจะถูกละเว้น (minute ?? 0เฉพาะเมื่อมีhour) - คำขอที่ส่ง
hourจะไม่มีฟิลด์birthHourและผลคำนวณเหมือนเดิม (ยกเว้นidentity·ohaengDeficientที่แนบมาตั้งแต่ 2026-10-10) ไคลเอนต์เดิมที่ส่งhourเสมอจะไม่ได้รับผลกระทบ ไคลเอนต์ที่สร้างตามพฤติกรรม "หากละไว้จะคำนวณตามเที่ยงวัน" ที่เคยมีอยู่ช่วงสั้นๆ ให้ตรวจbirthHour.known === falseแล้วแสดงช่องเสายามเป็น "ไม่ทราบ"strength·gyeokgukฯลฯ จะส่งเป็นค่าตาม 3 เสาเสมอ (ก่อน 2026-09-16 เคยถูกลบ) กลุ่มการปรึกษา (/reading·/reading/memory·/reading/report) ก็ส่งค่าตาม 3 เสาให้โมเดลด้วยกฎเดียวกัน
- ชื่อฟิลด์ภาษาเกาหลี: ชื่อฟิลด์ทั้งหมด (ก้านฟ้า กิ่งดิน ธาตุทั้งห้า ฯลฯ) เขียนเป็นภาษาเกาหลี แม้ส่ง
langชื่อฟิลด์ก็ยังคงเดิม และแปลเฉพาะค่า (ธาตุช่วย · คำอธิบายก้านวันเกิด · ทิศทางวัยจร · ชื่อดาวพิเศษ ฯลฯ) รหัสก้านฟ้า · กิ่งดิน · ธาตุทั้งห้า (stem·branch·ohaeng) และคีย์ของohaengBalanceเป็นฮันกึลเหมือนเดิมในทุกภาษา รายการทั้งหมดดูที่ ค่าที่ใช้ได้ > ค่ารหัสที่ไม่ขึ้นกับภาษา - ตัวเลือกเพิ่มเติมไม่บังคับทั้งหมด (2026-10-08): หากไม่ส่ง
lang·calendar·isLeapMonth·birthLatitude·birthLongitude·country·zaSiRule·birthTimePrecisionเลย ผลคำนวณจะเหมือนเดิม แต่ตั้งแต่ 2026-10-10 จะเพิ่มidentity·ohaengDeficientท้ายการตอบกลับเสมอ (ค่า · ลำดับของคีย์เดิมคงเดิม) ราคาก็ยังเป็น ₩50/ครั้งเหมือนเดิม - เปลี่ยนแปลง (2026-10-12): เปลี่ยนเกณฑ์การแปลงจันทรคติเป็นข้อมูลของสถาบันดาราศาสตร์และอวกาศเกาหลี (KASI) ผลของบางวันที่เปลี่ยนไป เดือนอธิกมาสที่ไม่มีอยู่จะไม่เปลี่ยนเป็นเดือนปกติ แต่ตอบด้วย 400
INVALID_LUNAR_DATE - อินพุตจันทรคติ: หากส่ง
calendar: "lunar"ระดับบนสุดของการตอบกลับจะมีรายละเอียดการแปลงlunarInputแนบมา ผลการปรับเวลาสุริยะจริงอยู่ในtrueSolarTimeตัวอย่างผลลัพธ์จริงของเอนจิน (จันทรคติ 1990-07-15 14:30 พิกัดปูซานlang: "en"):{ "year": 1990, "month": 7, "day": 15, "hour": 14, "minute": 30, "timezone": "Asia/Seoul", "gender": "male", "calendar": "lunar", "birthLatitude": 35.1796, "birthLongitude": 129.0756, "lang": "en" } → "lunarInput": { "calendar": "lunar", "lunarDate": "1990-07-15", "isLeapMonth": false, "leapMonthApplied": false, "solarDate": "1990-09-03" }, "trueSolarTime": { "originalLocal": "14:30", "correctedLocal": "14:07", "longitudeCorrection": -23.6976, "equationOfTime": 0.3241, "totalCorrectionMinutes": -23.4, "dayShift": 0, "dstApplied": false, "basis": "coords", ... }, "ilganSummary": "辛 Metal — Jewel energy. Sharp intellect and refined aesthetic sense.", "daeunDirection": "Forward" - อินพุตผิดพลาด: วันที่จันทรคติที่ไม่มีอยู่จริง (เช่น วันที่ 30 ของเดือนที่มีถึงวันที่ 29) จะได้ 400
INVALID_LUNAR_DATEคำขอที่ส่งละติจูด/ลองจิจูดเพียงค่าเดียวจะได้ 400INVALID_LOCATIONและไม่คิดค่าบริการ ข้อผิดพลาดด้านรูปแบบ เช่น ไม่มีtimezoneก็ได้ 400 (ไม่คิดค่าบริการ)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว (ไม่คิดค่าบริการ) |
| 402 | (ไม่มี) | ยอดคงเหลือน้อยกว่าค่าเรียก — API นี้ไม่ตรวจยอดคงเหลือก่อนเรียก จึงได้ 402 ที่ไม่มีรหัส |
API ดวงชะตาตลอดชีวิต
POST /api/v1/partners/v1/lifetime
คำนวณผังดวงจากวันเดือนปีและเวลาเกิด แล้วรวมย่อหน้าการอ่านดวงของส่วนประกอบที่ตรงกับผัง (เสาวัน · ก้านวันเกิด×กิ่งดินเดือน · ก้านวันเกิด×ความแข็ง-อ่อนของดวง · ก้านวันเกิด×ธาตุช่วย · ธาตุเกิน/ขาดสูงสุด 3 รายการ · กลุ่มสิบเทพที่แรงที่สุด) เป็น 7 หัวข้อ บุคลิกภาพ · การเงิน · อาชีพ · ความรัก · สุขภาพ · ความสัมพันธ์ · คำแนะนำ แล้วคืนให้ เป็นย่อหน้าที่เขียนด้วยทฤษฎีซาจูของ HRUM และอินพุตเดียวกันให้ผลเดียวกันเสมอ การตัดสินผังดวงเหมือนกับ API ปฏิทินหมื่นปี
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
year · month · day | number | O | ปีเกิด (1900-2100) · เดือน · วัน (ค่าเริ่มต้นสุริยคติ หาก calendar: "lunar" เป็นจันทรคติ) |
hour · minute | number | เวลาเกิด หากละ hour จะคำนวณด้วยกฎกรณีไม่ทราบเวลาเกิดเดียวกับ API ปฏิทินหมื่นปี (ตาม 3 เสา ปี · เดือน · วัน) | |
timezone | string | O | เขตเวลา (เช่น Asia/Seoul) หากเป็นชื่อที่ไม่รู้จัก จะคำนวณด้วยเขตเวลาเริ่มต้นและการตอบกลับจะมี warnings (UNKNOWN_TIMEZONE) แนบมา |
gender | string | O | "male" หรือ "female" |
topic | string | เมื่อต้องการหัวข้อเดียว: personality, wealth, career, love, health, relationships, advice หากละไว้จะได้ทั้ง 7 หัวข้อ | |
lang | string | ko (ค่าเริ่มต้น) · en · ja · th | |
layers | string[] | ชั้นการอ่านดวงเพิ่มเติม: "astro" (ราศี — ดวงอาทิตย์ · ดวงจันทร์ · ลัคนา) · "ziwei" (จื่อเวยโต่วซู่ — ดาวหลักของวังชะตา + ดาวหลักของวังตามหัวข้อ) จะต่อท้ายย่อหน้าซาจูของแต่ละหัวข้อตามลำดับ ราศี → จื่อเวยโต่วซู่ หากละไว้หรือเป็น [] การตอบกลับจะเหมือนตอนนี้ทุกอย่าง | |
calendar · isLeapMonth | string · boolean | หากเป็น "lunar" จะรับ year · month · day เป็นจันทรคติแล้วแปลงเป็นสุริยคติเพื่อคำนวณ (ค่าเริ่มต้น "solar") isLeapMonth: true คือเดือนอธิกมาส หากปีนั้นไม่มีเดือนอธิกมาสนั้นจะได้ 400 INVALID_LUNAR_DATE (ตั้งแต่ 2026-10-12) หากส่งเป็นจันทรคติ การตอบกลับจะมี lunarInput (รูปแบบเดียวกับ API ปฏิทินหมื่นปี) แนบมา | |
birthLatitude · birthLongitude | number | พิกัดสถานที่เกิด (ส่งทั้งสองค่าพร้อมกัน) ย่อหน้าซาจูและ layers ปรับเวลาสุริยะจริงด้วยเกณฑ์เดียวกัน เส้นเมริเดียนมาตรฐานกำหนดจากเวลามาตรฐานของ timezone (ไม่รวมเวลาออมแสง) ลัคนาจะออกมาเมื่อมีทั้งเวลาเกิดและพิกัด | |
country | string | รหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับด้วยลองจิจูดตัวแทนของประเทศนั้น (ประเทศอื่นไม่มีการปรับ) layers ก็ใช้ประเทศนี้ (หากละไว้จะประมาณจาก lang) | |
zaSiRule | string | เสาวันของยามจื่อ (หลัง 23 นาฬิกา): "traditional" (ค่าเริ่มต้น เสาวันของวันถัดไป) · "yajaSi" (ยามจื่อกลางคืน เสาวันของวันนั้น · หลังปรับตามตำแหน่ง ก้านฟ้าของเสายามช่วง 23 นาฬิกาอิงก้านวันเกิดของวันถัดไป ตั้งแต่ 2026-10-20) ใช้เฉพาะกับย่อหน้าซาจู (จื่อเวยโต่วซู่กำหนดตายตัวให้ตั้งแต่ 23 นาฬิกาเป็นวันถัดไป) | |
birthTimePrecision | string | exact · approximate · estimated · unknown การปรับตามตำแหน่งใช้เฉพาะเมื่อเป็น exact หากละไว้แต่ส่งพิกัดหรือ country จะถือเป็น exact |
ตัวอย่างคำขอ
{
"year": 1990, "month": 9, "day": 4, "hour": 14, "minute": 30,
"timezone": "Asia/Seoul", "gender": "male",
"topic": "career", "lang": "ko"
}
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"topics": [
{
"topic": "career",
"paragraphs": [
{ "component": "ilju", "key": "임신", "text": "..." },
{ "component": "ilgan_wolji", "key": "임_신", "text": "..." },
{ "component": "ilgan_strength", "key": "임_신강", "text": "..." },
{ "component": "ilgan_yongshin", "key": "임_화", "text": "..." },
{ "component": "ohaeng_state", "key": "목_lack", "text": "..." },
{ "component": "ohaeng_state", "key": "토_lack", "text": "..." },
{ "component": "ohaeng_state", "key": "수_lack", "text": "..." },
{ "component": "top_sipsin", "key": "인성", "text": "..." }
]
}
],
"lang": "ko",
"fallbackLanguage": null,
"engine": { "version": 1, "styleVersion": "v1" }
}
}
topicsเรียงตาม 7 หัวข้อข้างต้นเสมอ ย่อหน้าภายในหัวข้อเรียงตามลำดับส่วนประกอบ (เสาวัน → ก้านวันเกิด×กิ่งดินเดือน → ความแข็ง-อ่อนของดวง → ธาตุช่วย → สถานะธาตุทั้งห้า → กลุ่มสิบเทพ)keyเป็นค่าการตัดสินภาษาเกาหลี (ไม่ขึ้นกับภาษา)ohaeng_stateมี 0~3 รายการตามผัง- ภาษา: หากยังไม่มีย่อหน้าในภาษาที่ขอ เฉพาะย่อหน้านั้นจะส่งเป็นภาษาเกาหลีและแสดง
fallbackLanguage: "ko" - การปรับเวลา: หากไม่ส่งพิกัด ·
countryจะคำนวณตามเวลาที่ป้อนเลย (เหมือน API ปฏิทินหมื่นปี) หากต้องการย่อหน้าเดียวกับแอป INTA (ภาษาเกาหลี ป้อนเวลาเอง) ให้ส่งcountry: "KR"ผู้ที่เกิดต่างประเทศtimezoneอย่างเดียวจะไม่ถูกปรับ จึงต้องส่งพิกัดมาด้วย - เปลี่ยนแปลง 2026-10-11: หากส่งพิกัด ย่อหน้าซาจูก็จะปรับเวลาสุริยะจริงด้วย (ก่อนหน้านี้ใช้เฉพาะกับ
layers) เป็นการแก้ไขให้ซาจู · ราศี · จื่อเวยโต่วซู่ในการตอบกลับเดียวกันใช้เกณฑ์เวลาเดียวกัน การเรียกที่เคยส่งพิกัดจึงอาจได้ย่อหน้าซาจูที่เปลี่ยนไป ส่วนการตอบกลับของการเรียกที่ไม่ได้ส่งฟิลด์ใหม่และพิกัดยังเหมือนเดิม
ชั้นราศี · จื่อเวยโต่วซู่ (layers)
มีโครงสร้างเดียวกับดวงชะตาตลอดชีวิตของแอป INTA ราศีเพิ่มย่อหน้าราศีของดวงอาทิตย์ · ดวงจันทร์ · ลัคนา และจื่อเวยโต่วซู่เพิ่มย่อหน้าของชุดดาวหลักในวังชะตา (Ming) หัวข้อละหนึ่งย่อหน้า แล้วต่อด้วยย่อหน้าดาวหลักของวังที่รับผิดชอบหัวข้อนั้น — การเงิน (wealth) = วังทรัพย์ (Cai Bo), การงาน (career) = วังขุนนาง (Guan Lu), ความรัก (love) = วังคู่ครอง (Fu Qi), สุขภาพ (health) = วังโรคภัย (Ji E) หัวข้อบุคลิกภาพ · ความสัมพันธ์ · คำแนะนำจะมีเฉพาะย่อหน้าวังชะตา ย่อหน้าแรกของแต่ละชั้นจะมี label (เช่น "별자리로 보면") แนบมา ใช้เป็นหัวข้อย่อยบนหน้าจอได้ หากระบุ topic ชั้นต่างๆ ก็จะแนบเฉพาะย่อหน้าของหัวข้อนั้น
{
"year": 1990, "month": 9, "day": 4, "hour": 14, "minute": 30,
"timezone": "Asia/Seoul", "gender": "male",
"birthLatitude": 37.5665, "birthLongitude": 126.978,
"topic": "career", "lang": "ko",
"layers": ["astro", "ziwei"]
}
{
"success": true,
"data": {
"topics": [
{
"topic": "career",
"paragraphs": [
{ "component": "ilju", "key": "임신", "text": "..." },
...
{ "component": "top_sipsin", "key": "인성", "text": "..." },
{ "component": "astro_sun", "key": "vir", "text": "...", "label": "별자리로 보면" },
{ "component": "astro_moon", "key": "pis", "text": "..." },
{ "component": "astro_asc", "key": "sag", "text": "..." },
{ "component": "ziwei_ming", "key": "tt_jm", "text": "...", "label": "자미두수로 보면" },
{ "component": "ziwei_palace", "key": "cr_tj", "text": "..." }
]
}
],
"lang": "ko",
"fallbackLanguage": null,
"engine": { "version": 1, "styleVersion": "v1" },
"missingSections": 0,
"layers": {
"astro": { "included": true, "costWon": 20, "note": null },
"ziwei": { "included": true, "costWon": 20, "note": null }
}
}
}
key: ราศีเป็นตัวย่อภาษาอังกฤษ 3 ตัวอักษร (vir=ราศีกันย์ ฯลฯ) จื่อเวยโต่วซู่เป็นชุดตัวย่อของดาวหลักในวังชะตา (tt_jm=Tian Tong · Ju Men หากไม่มีดาวหลักเป็นempty)ziwei_palace: ย่อหน้าของวังตามหัวข้อkeyคือpalace abbreviation_main-star abbreviation(ตัวย่อวัง_ตัวย่อดาวหลัก) (wl=วังทรัพย์ ·cr=วังขุนนาง ·sp=วังคู่ครอง ·hl=วังโรคภัย เช่นcr_tj=วังขุนนาง Tian Ji) หากวังมีดาวหลักสองดวง ย่อหน้าก็มีสองย่อหน้า วังที่ไม่มีดาวหลัก (วังว่าง) จะไม่แนบ อยู่ถัดจากย่อหน้าวังชะตาทันทีและไม่มีlabel(เฉพาะเมื่อหัวข้อนั้นไม่มีย่อหน้าวังชะตา ย่อหน้าวังแรกจึงจะมีlabel) ราคายังเป็นชั้นจื่อเวยโต่วซู่ +₩20 เหมือนเดิม- หากไม่มีเวลาเกิด: ชั้นจื่อเวยโต่วซู่จะถูกตัดออก และ
layers.ziweiจะมี"included": false,"reason": "birth_time_required"พร้อมข้อความแนะนำ (note) ส่วนราศีจะแนบเฉพาะดวงอาทิตย์ (และดวงจันทร์หากราศีจันทร์แน่นอน) ตามเวลาเที่ยงวัน - หากไม่มีพิกัด: ย่อหน้าลัคนาจะถูกตัดออก และ
layers.astro.noteจะระบุเหตุผล หากไม่ส่งcountryประเทศเกิดของชั้นจะประมาณจากlang(ko→เกาหลี, ja→ญี่ปุ่น, th→ไทย) reasonเป็นหนึ่งในbirth_time_required·chart_unavailable·narrative_unavailableและชั้นที่ถูกตัดออกจะไม่คิดค่าบริการmissingSections: จำนวนย่อหน้าที่ควรมีแต่ถูกตัดเพราะยังไม่มีประโยคการอ่านดวง (หัวข้อพื้นฐาน + ชั้นที่แนบ) ถ้าเป็น 0 แสดงว่าไม่มีย่อหน้าขาด แม้บางส่วนขาดไปราคาก็เท่าเดิม
ราคา
- ทั้งหมด (7 หัวข้อ) ₩100/ครั้ง ระบุ
topic₩20/ครั้ง คิดค่าบริการเฉพาะการเรียกที่สำเร็จ และการเรียกซ้ำด้วยอินพุตเดิมก็คิดค่าบริการแยกกัน (Idempotency) layers: +₩20 ต่อชั้นที่มีย่อหน้าแนบจริง (เหมือนกันทั้งแบบทั้งหมด · หัวข้อเดียว) ตัวอย่าง: ทั้งหมด + ราศี + จื่อเวยโต่วซู่ = ₩140 ยอดคงเหลือจะตรวจล่วงหน้าด้วยยอดที่รวมชั้นที่ขอไว้แล้ว- อินพุตผิดพลาด (400) · ยอดคงเหลือไม่พอ (402) · ดึงย่อหน้าล้มเหลว (503
lifetime_narrative_unavailable) ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือlifetime - ตัวเลือกอินพุต: อินพุตการเกิดเหมือนกับ API ปฏิทินหมื่นปี (
calendar·isLeapMonth· พิกัด ·country·zaSiRule·birthTimePrecision) ไม่รับตัวเลือกเฉพาะของปฏิทินหมื่นปี (astrology·glossary·name) หากส่งมาจะได้ 400 (ไม่คิดค่าบริการ) - หากบัญชียังไม่ได้เปิดฟีเจอร์นี้จะได้ 404
lifetime_not_enabled(ไม่คิดค่าบริการ)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | lifetime_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอเมื่อตรวจล่วงหน้าด้วยยอดที่รวมชั้นที่ขอไว้ |
| 503 | lifetime_narrative_unavailable | ดึงย่อหน้าการอ่านดวงไม่ได้ (ไม่คิดค่าบริการ) |
API ผังดวงจื่อเวยโต่วซู่
POST /api/v1/partners/v1/ziwei-chart
คำนวณผังดวงจื่อเวยโต่วซู่ (Zi Wei Dou Shu) จากวันเดือนปีและเวลาเกิด คืน 12 วัง (ชื่อวัง · ก้านฟ้า · กิ่งดิน · อายุช่วงใหญ่) 14 ดาวหลักและดาวเสริม (รวมความสว่าง · สี่การแปรของปีเกิด) สำนักธาตุ ตำแหน่งวังชะตา · วังกาย สี่การแปรของปีเกิด และช่วงใหญ่ · ปีจรของวันอ้างอิง อินพุตเดียวกันให้ผลเดียวกันเสมอ ป้ายกำกับจะเติมเป็นภาษาที่ขอ ส่วน key เป็นค่าภาษาอังกฤษตายตัวที่ไม่ขึ้นกับภาษา
การตั้งค่าการคำนวณ (ตายตัว)
- เดือนอธิกมาส: ถึงวันที่ 15 ของเดือนอธิกมาสถือเป็นเดือนนั้น ตั้งแต่วันที่ 16 ถือเป็นเดือนถัดไป
- เกิดช่วง 23 นาฬิกา: คำนวณเป็นยามจื่อของวันถัดไป (มีข้อความแนะนำใน
notes.lateZiNotice) - เส้นแบ่งปี: วันที่ 1 เดือน 1 ตามจันทรคติ (ซอลลัล) หากเกิดระหว่างลี่ชุน (Ipchun)~ซอลลัล ก้าน-กิ่งของปีอาจต่างจากซาจู (ที่อิงลี่ชุน) และในกรณีนี้
chart.yearBasisNoteจะมีข้อความแนะนำแนบมา - การปรับเวลา: กฎเดียวกับซาจู ค่าเริ่มต้นคือใช้เวลาที่ป้อนเลย (เหมือน API ปฏิทินหมื่นปี) หากส่ง
birthTimePrecision: "exact"พร้อมพิกัด (birthLatitude·birthLongitude) หรือcountryCode(KR · JP · TH) จะปรับเป็นเวลาสุริยะจริง ผลการปรับแสดงในclock - สี่การแปร: วิธีวางดาวของสำนักซานเหอ + สี่การแปรของปีเกิด เอนจินกำหนดตายตัวเป็น iztro 2.6.1 (
chart.engine)
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
year · month · day | number | O | ปีเกิด (1900-2100) · เดือน · วัน |
hour | number | O | ชั่วโมงเกิด (0-23) จื่อเวยโต่วซู่ตั้งผังดวงไม่ได้หากไม่มีเวลาเกิด — หากละไว้จะได้ 400 birth_time_required |
minute | number | นาทีเกิด (0-59) หากละไว้เป็น 0 | |
gender | string | O | "male" หรือ "female" (กำหนดทิศทางเดินของช่วงใหญ่) |
calendar | string | solar (ค่าเริ่มต้น) หรือ lunar | |
isLeapMonth | boolean | true หากเป็นเดือนอธิกมาสตามจันทรคติ อินพุตสุริยคติจะละเว้น หากปีนั้นไม่มีเดือนอธิกมาสนั้น จะคำนวณเป็นเดือนปกติและ chart.lunarDate.isLeapMonth จะเป็น false | |
birthTimePrecision | string | exact (ปรับเวลาสุริยะจริง) หรือ approximate (ไม่ปรับ + notes.approximateTimeNote) หากละไว้จะไม่ปรับ | |
birthLatitude · birthLongitude | number | พิกัดสถานที่เกิด (สำหรับการปรับแบบ exact) | |
countryCode | string | ISO 2 ตัวอักษรของประเทศเกิด ตัวพิมพ์ใหญ่เท่านั้น (เช่น KR — kr ได้ 400) เมื่อไม่มีพิกัดจะปรับด้วยลองจิจูดตัวแทน | |
birthTimezoneOffset | number | ค่าชดเชย UTC ของเวลาเกิด (นาที 540 = KST) | |
referenceDate | string | วันอ้างอิงของช่วงใหญ่ · ปีจร YYYY-MM-DD (ค่าเริ่มต้น: วันนี้ ตามเวลาเกาหลี) | |
lang | string | ko (ค่าเริ่มต้น) · en · ja · th | |
timezone | string | เพื่อความเข้ากันได้กับ API ปฏิทินหมื่นปี (ไม่ได้ใช้ในการคำนวณ แม้เป็นชื่อที่ไม่รู้จักก็ไม่มีคำเตือน) | |
readings | boolean | หากเป็น true การตอบกลับจะแนบ readings (ย่อหน้าการอ่านดวงของชุดดาวหลักในวังชะตา · 7 หัวข้อ · ดาวหลักในวังทรัพย์/วังขุนนาง/วังคู่ครอง/วังโรคภัย ในภาษา lang) เพิ่ม ₩20 (รวม ₩70) หากละไว้การตอบกลับจะเหมือนเดิม |
ตัวอย่างคำขอ
{
"year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30,
"gender": "female", "referenceDate": "2026-10-08", "lang": "ko"
}
ตัวอย่างการตอบกลับ (บางส่วน)
{
"success": true,
"data": {
"engineVersion": 1,
"lang": "ko",
"referenceDate": "2026-10-08",
"clock": {
"inputSolarDate": "1990-05-15", "inputTime": "14:30",
"correctedSolarDate": "1990-05-15", "correctedTime": "14:30",
"correctionMinutes": 0, "dstApplied": false, "basis": null,
"hourBranch": { "key": "wei", "label": "미" }
},
"chart": {
"engine": { "name": "iztro", "version": "2.6.1", "config": { ... } },
"solarDate": "1990-05-15",
"lunarDate": { "year": 1990, "month": 4, "day": 21, "isLeapMonth": false },
"yearGanzhi": "경오",
"yearBasisNote": null,
"fiveElementsClass": { "key": "earth5", "label": "토오국" },
"soulPalaceBranch": { "key": "xu", "label": "술" },
"bodyPalaceBranch": { "key": "zi", "label": "자" },
"palaces": [
...,
{
"key": "ming", "label": "명궁",
"branch": { "key": "xu", "label": "술" },
"stem": { "key": "bing", "label": "병" },
"isBodyPalace": false,
"majorStars": [
{ "key": "ziwei", "label": "자미", "brightness": { "key": "de", "label": "득" }, "mutagen": null },
{ "key": "tianxiang", "label": "천상", "brightness": { "key": "de", "label": "득" }, "mutagen": null }
],
"minorStars": [
{ "key": "lingxing", "label": "영성", "brightness": { "key": "miao", "label": "묘" }, "mutagen": null }
],
"decadal": { "from": 5, "to": 14, "isCurrent": false }
},
...
],
"mutagens": [
{ "type": "lu", "label": "화록", "starKey": "taiyang", "starLabel": "태양", "palaceKey": "children", "palaceLabel": "자녀궁" },
{ "type": "quan", "label": "화권", "starKey": "wuqu", "starLabel": "무곡", "palaceKey": "wealth", "palaceLabel": "재백궁" },
{ "type": "ke", "label": "화과", "starKey": "taiyin", "starLabel": "태음", "palaceKey": "children", "palaceLabel": "자녀궁" },
{ "type": "ji", "label": "화기", "starKey": "tiantong", "starLabel": "천동", "palaceKey": "health", "palaceLabel": "질액궁" }
],
"currentDecadal": { "palaceKey": "children", "from": 35, "to": 44 },
"yearly": { "palaceKey": "wealth", "year": 2026 }
},
"features": [
"bright:紫微=得", "co:紫微+天相@命", "cs:命=胎", "dir:逆", "hua:祿=太陽@子女",
"lhua:忌=廉貞@流年", "limit:大限@子女", "limit:小限@辰", "ming:戌", "mingzhu:祿存",
"star:天姚@辰", "star:紫微@命", "year:庚", "yy:陽女", ...
],
"notes": { "lateZiNotice": null, "approximateTimeNote": null }
}
}
หากส่ง "lang": "ja" ในคำขอเดียวกัน จะเปลี่ยนเฉพาะป้ายกำกับ — ตัวอย่าง: "yearGanzhi": "庚午", วังชะตา "label": "命宮", ดาวหลัก "紫微" · "天相", สำนักธาตุ "土五局", สี่การแปร "化禄"
palacesมี 12 รายการเสมอ เรียงตามลำดับกิ่งดิน อิน → ชุก (อิน เมียว จิน ซา โอ มี ชิน ยู ซุล แฮ จา ชุก) แยกประเภทวังด้วยkey(ming,siblings,spouse,children,wealth,health,travel,friends,career,property,fortune,parents)mutagensคือสี่การแปรของปีเกิด (Hua Lu · Hua Quan · Hua Ke · Hua Ji) และวังที่ดาวนั้นอยู่mutagenของอ็อบเจกต์ดาวก็เป็นสี่การแปรของปีเกิดfeaturesคืออาร์เรย์สตริงที่เรียงแล้ว ซึ่งบันทึกข้อเท็จจริงที่เป็นจริงในผังดวงนี้ด้วยคีย์กฎของจื่อเวยโต่วซู่ (<kind>:<body>ใช้โทเค็นฮันจาแบบคลาสสิก) (ประมาณ 1,200 รายการต่อผัง ประมาณ 27KB) ครอบคลุมตำแหน่งดาว · ความสว่าง · สี่การแปรของปีเกิด · วังเดียวกัน · วังตรงข้าม · สามทิศสี่ตรง · การขนาบ (jia) · ก้านของวัง · สำนักธาตุ · วังชะตา/วังกาย · นาบึม · หยิน-หยาง · ทิศทางช่วงใหญ่ · วังของรอบดวงและดาวในวังนั้น รวมถึงตำแหน่งดาวย่อยที่ไม่ได้แสดงแยกในผัง · 12 ฉางเซิง · ช่วงเล็ก · สี่การแปรของช่วงใหญ่/ปีจร · ดาวเจ้าชะตา · ดาวเจ้ากาย · วังเหตุเดิม จึงนำเงื่อนไขกฎมาเทียบด้วยการเปรียบเทียบสตริงได้ เพราะเรื่องขนาด จึงตัดออกเพียงสองอย่าง:co·meetของสามดาว (co:A+B+C=co:A+Bและco:A+C,meetก็เช่นกัน) และคีย์ความสัมพันธ์ที่มีดาวย่อยเกี่ยวข้อง (นับด้วยstar:<minor star>@<branch>กับpal:·shen:·limit:โดยวังตรงข้าม +6, สามทิศสี่ตรง 0 · ±4 · +6, การขนาบ ±1 ได้)- การอ้างอิงต้นฉบับในการ์ดหลักฐานของกฎ: ใน
sourcesของการ์ดกฎจื่อเวยโต่วซู่ (ฐานข้อมูลการตีความ เฉพาะพาร์ทเนอร์ที่ได้รับอนุญาต) การอ้างอิงที่ยืนยันไม่ได้จากต้นฉบับสาธารณะ (ฉบับสาธารณสมบัติ) (ที่เป็นmatch: "PARTIAL"และไม่มีตำแหน่งในต้นฉบับfoundAt) จะตัดต้นฉบับ (quote) และตำแหน่ง (location) ออก แล้วส่งเป็น"citation": "pending"(กำลังตรวจสอบแหล่งที่มา) ประโยคกฎและsourceIdคงเดิม การอ้างอิงที่ยืนยันจากต้นฉบับแล้ว (match: "EXACT") การอ้างอิงPARTIALที่ยืนยันตำแหน่งในต้นฉบับ (foundAt) แล้ว และหลักฐานจากเอนจินจะไม่เปลี่ยน เป็นการจัดการเพื่อไม่ให้การอ้างอิงที่ยังไม่ยืนยันแหล่งที่มาดูเหมือนเป็นแหล่งที่มา - การอ้างอิงจากฉบับสืบทอด (
match: "QUOTED"): เป็นการอ้างอิงจากฉบับสืบทอดที่ไม่มีหลักยึด PD จะส่งต้นฉบับ (quote) และตำแหน่ง (location) ตามเดิม การอ้างอิงที่มีร่องรอยการตรวจชำระ · เทียบเคียงต้นฉบับไม่เข้าข่ายนี้ currentDecadalเป็นnullหากยังไม่ถึงอายุเริ่มช่วงใหญ่แรกyearly.yearคือปีจันทรคติตามเกณฑ์ปีจร (หากก่อนซอลลัลจะเป็นปีก่อนหน้า)- หาก
readings: trueจะได้readings={ ming, topics[], palaces[], lang, costWon, missingSections, version }mingคือย่อหน้าชุดดาวหลักในวังชะตา (key·text·lang)topicsคือย่อหน้าตามหัวข้อ (topic·text·lang)palacesคือย่อหน้าตามวัง · ดาวหลัก (palace·star·text·lang) ย่อหน้าที่ไม่มีประโยคในภาษาที่ขอจะมาเป็นภาษาเกาหลี และlangของย่อหน้านั้นจะเป็นkomissingSectionsคือจำนวนย่อหน้าที่ถูกตัดเพราะยังไม่มีประโยคการอ่านดวง (0 คือมีครบ) แม้บางส่วนขาดไปค่าบริการเพิ่มก็เท่าเดิมversionเป็นเครื่องหมายฉบับของพจนานุกรมการอ่านดวงที่ใช้อ่านย่อหน้า (เช่นnr-3f9a0c1d2e4b) ค่าเท่ากันคือประโยคเดียวกัน และเมื่อแก้ประโยคในพจนานุกรม ค่าจะเปลี่ยน ใช้เพื่อเปรียบเทียบเท่านั้น อย่าตีความรูปแบบ
เมื่อไม่มีเวลาเกิด (400)
{
"success": false,
"statusCode": 400,
"code": "birth_time_required",
"message": "Zi Wei Dou Shu needs the birth hour (hour 0-23). ...",
"partial": {
"birthYearMutagens": [
{ "type": "lu", "label": "화록", "starKey": "taiyang", "starLabel": "태양" },
...
],
"yearStemStars": [
{ "key": "lucun", "label": "녹존", "branch": { "key": "shen", "label": "신" } },
...
]
}
}
จะคืนเฉพาะกิ่งดินของดาวในสี่การแปรของปีเกิดที่ยืนยันได้แม้ไม่มีเวลา และดาวที่กำหนดด้วยก้านปี (Lu Cun · Qing Yang · Tuo Luo · Tian Kui · Tian Yue) เป็น partial การจัดวางวังต้องมีเวลาจึงจะกำหนดได้ อย่าแต่งขึ้นเอง การตอบกลับนี้ไม่คิดค่าบริการ
ราคา
- ₩50/ครั้ง หาก
readings: true+₩20 (รวม ₩70) คิดค่าบริการเฉพาะการเรียกที่สำเร็จ และการเรียกซ้ำด้วยอินพุตเดิมก็คิดค่าบริการแยกกัน (Idempotency) - อินพุตผิดพลาด (400
invalid_birth_date·birth_time_requiredฯลฯ) · ยอดคงเหลือไม่พอ (402) ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือziwei_chart - ข้อผิดพลาดอื่นที่ไม่คิดค่าบริการ: 404
ziwei_not_enabled(บัญชียังไม่เปิดฟีเจอร์) · 404ziwei_readings_not_enabled(ยังไม่เปิดย่อหน้าการอ่านดวง) · 503ziwei_readings_unavailable(ดึงย่อหน้าการอ่านดวงไม่ได้)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | ziwei_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 404 | ziwei_readings_not_enabled | readings: true แต่ยังไม่เปิดย่อหน้าการอ่านดวง |
| 400 | invalid_birth_date | วันที่สุริยคติที่ไม่มีอยู่จริง หรืออยู่นอกช่วงวัน · เดือนอธิกมาสตามจันทรคติ |
| 400 | birth_time_required | ไม่มี hour — จะได้ partial มาด้วยเหมือนตัวอย่างด้านบน |
| 400 | reference_date_before_birth | referenceDate มาก่อนวันเกิด |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
| 503 | ziwei_readings_unavailable | ดึงย่อหน้าการอ่านดวงไม่ได้ |
ทั้งหมดไม่คิดค่าบริการ
อัตลักษณ์ซาจู (รวมอยู่ในปฏิทินหมื่นปี)
ตั้งแต่ 2026-10-10 เนื้อหาอัตลักษณ์ซาจูจะคืนมาพร้อมกันในฟิลด์ identity ของการตอบกลับ API ปฏิทินหมื่นปี — สามภัย (samjae) · ดาวพิเศษ (sinsal_list) · ช่องว่าง (gongmang) · การหยั่งราก (rooting_hints) · ความแข็ง-อ่อนตามฤดู (season_strength_hint) · ไทม์ไลน์วัยจร 10 ปี/ดวงรายปี (timeline) · MBTI ซาจู (mbti_inference) ไม่มีค่าบริการเพิ่มนอกเหนือจากราคาปฏิทินหมื่นปี POST /api/v1/partners/v1/identity เดิมยังทำงานตามเดิมไปอีกระยะหนึ่งสำหรับพาร์ทเนอร์ที่เชื่อมต่อไว้แล้ว การเชื่อมต่อใหม่ให้ใช้ปฏิทินหมื่นปี
- เฮดเดอร์แจ้งการเลิกใช้: การตอบกลับของ
/identityจะมีDeprecation: trueและLink: </api/v1/partners/v1/manseryeok>; rel="successor-version"แนบมา ยังไม่ได้กำหนดวันสิ้นสุด (Sunset) - ความต่างจาก
identityของปฏิทินหมื่นปี: คีย์ที่มีอยู่แล้วในการตอบกลับของปฏิทินหมื่นปี (saju·sipsin_map·strength·yongshin·gyeokguk·cheongan_detail·hap_chung_report·heoja_report·gongmang_detail·ohaeng_byeonsu_hits) จะไม่อยู่ในidentityค่าเดียวกันให้อ่านจากฟิลด์ระดับบนสุดของปฏิทินหมื่นปี (wonkuk·strength·yongshinDetail·gyeokgukDetailฯลฯ) currentYear·windowSize: ปฏิทินหมื่นปีไม่รับพารามิเตอร์สองตัวนี้ (ส่งมาจะได้ 400) หากต้องเปลี่ยนปีอ้างอิง · ช่วงของไทม์ไลน์ ให้ใช้/identityไปก่อน- ชื่อสิบเทพเป็นค่ารหัส: ค่าของ
sipsin_map(ก้านฟ้า · กิ่งดินของปี · เดือน · ยาม และกิ่งดินวัน) (비견·정관ฯลฯ) จะส่งเป็นค่ารหัสภาษาเกาหลีไม่ว่าlangจะเป็นอะไร ชื่อที่จะแสดงบนหน้าจอให้ใช้คำแปลจากอภิธานศัพท์ (glossaryในภาษาlang) ที่ได้จากการส่งglossary: trueในคำขอปฏิทินหมื่นปี รายการทั้งหมดดูที่ ค่าที่ใช้ได้ > ค่ารหัสที่ไม่ขึ้นกับภาษา - ไม่ทราบเวลาเกิด:
/identityคำนวณตามเที่ยงวัน ส่วนidentityของปฏิทินหมื่นปีคำนวณจาก 3 เสา ปี · เดือน · วัน เหมือนเนื้อหาหลักของปฏิทินหมื่นปี เมื่อ/identityคำนวณจาก 3 เสา (birthHour.basis=three_pillars)saju.hourจะเป็น{ "cheongan": "", "jiji": "", "ohaeng": null }(ตั้งแต่ 2026-10-16ohaengเป็นnullหมายถึงไม่มีเสายาม) จำนวนธาตุทั้งห้าไม่รวมเสายาม - ราคา:
/identityเดิม ₩10/ครั้ง (เฉพาะเมื่อเปิดในบัญชี หากไม่เปิดจะได้ 404identity_not_enabled)identityของปฏิทินหมื่นปีไม่มีค่าบริการเพิ่ม endpoint ในบันทึกการใช้งานคือidentity
POST /api/v1/partners/v1/identity (เอนด์พอยต์เดิม)
เนื้อหาคำขอเหมือนกับ API ปฏิทินหมื่นปี และรับ currentYear (1900~2200) · windowSize (1~10) เพิ่ม หากไม่รู้จัก timezone การตอบกลับจะมี warnings แนบมาเหมือนปฏิทินหมื่นปี
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/identity \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "year": 1990, "month": 5, "day": 15, "hour": 12, "minute": 0, "timezone": "Asia/Seoul", "gender": "male" }'
ตัวอย่างการตอบกลับ (ตัดตอน ผลลัพธ์จริงของเอนจิน)
{
"success": true,
"data": {
"saju": {
"year": { "cheongan": "경", "jiji": "오", "ohaeng": "금" },
"month": { "cheongan": "신", "jiji": "사", "ohaeng": "금" },
"day": { "cheongan": "경", "jiji": "진", "ohaeng": "금" },
"hour": { ... }
},
"sipsin_map": { "year_cheongan": "비견", "year_jiji": "정관", "month_cheongan": "겁재", ... },
"strength": { "dayMaster": "경", "score": -60, "result": "신약", "level": "중약", ... },
"rooting_hints": { ... },
"season_strength_hint": { "season": "여름", "strength_label": "최약(最弱)", ... },
"sinsal_list": [ { "id": "shinsal_haksang", "name": "학당", "name_hanja": "學堂", "category": "길신", ... } ],
"gongmang": { "sun": "갑술순", "void_branches": ["신", "유"], "hits": [] },
"samjae": { "is_in_samjae": false, "current_year_branch": "오" },
"yongshin": { "method": "조후", "primary": "수", ... },
"timeline": { "current": { "daeun": { "startAge": 27, "endAge": 37, "stem": "갑", "branch": "신", ... }, ... } },
"gyeokguk": { "primary": "비견격", ... },
"mbti_inference": { "e_i": 48, "s_n": -8, "t_f": 16, "j_p": -18, "inferred": "ESFJ", ... },
...
}
}
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | identity_not_enabled | บัญชียังไม่ได้เปิด |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
API เปรียบเทียบซาจู ↔ MBTI
POST /api/v1/partners/v1/saju-mbti
ส่งข้อมูลการเกิดพร้อม MBTI ของบุคคลนั้น แล้วจะคืนผังดวง (4 เสา หากไม่ทราบเวลาเกิดเป็น 3 เสา) พร้อมการเปรียบเทียบที่วางแนวโน้มที่เห็นจากซาจูและMBTI ที่ป้อนไว้เคียงกันในทุกแกนของ MBTI ทั้ง 4 แกน (E · I / S · N / T · F / J · P) คำนวณอย่างเดียวโดยไม่ใช้ LLM ราคาต่อครั้งคือ ₩10/ครั้ง เท่ากับอัตลักษณ์ซาจู (คิดค่าบริการเฉพาะเมื่อสำเร็จ)
การตีความนี้ไม่ใช่ทฤษฎีโหราศาสตร์จีนแบบคลาสสิก แต่เป็นแนวทางการตีความสมัยใหม่ ตั้งแต่ kbVersion 2026.10.16-2 กฎการตีความเป็นฉบับอิงเอกสารที่เทียบกับเอกสารสมัยใหม่แล้ว (การตอบกลับ interim: false, kbStatus: "literature") สองฟิลด์นี้คงไว้เพื่อไม่ให้รูปแบบการตอบกลับเปลี่ยน กฎชั่วคราวที่ไม่มีหลักฐานทางเอกสารถูกปลดออกแล้ว และ ID กฎที่ถูกปลดจะไม่ถูกนำกลับมาใช้อีก ไม่มีการตัดสินว่าฝั่งไหนถูกหรือผิด และไม่ตัดสินดวงสมพงษ์ระหว่างประเภท
- อินพุตการเกิด: รับฟิลด์เดียวกับ API ปฏิทินหมื่นปี (
year·month·day·hour·minute·timezone·gender·calendar·isLeapMonth· การปรับตามตำแหน่ง ฯลฯ) ไม่รับcurrentYear·windowSize(ส่งมาจะได้ 400) mbti(จำเป็น): สตริง 4 ตัวอักษร ("INFJ"ไม่สนตัวพิมพ์เล็ก-ใหญ่ แต่ละตำแหน่งเป็น E/I · S/N · T/F · J/P) หรืออ็อบเจกต์จำนวนเต็ม 0~100 ต่อแกน{ "E_I": 30, "S_N": 45, "T_F": 80, "J_P": 60 }100 คือตัวอักษรหน้า (E · S · T · J) และถ้า 50 ขึ้นไปจะอ่านเป็นตัวอักษรหน้า หากส่งเป็น 4 ตัวอักษร จะแปลงตัวอักษรหน้าเป็น 75 ตัวหลังเป็น 25 และถือเป็นระดับ "เล็กน้อย"- ระดับ (
band): หาก |ค่า − 50| น้อยกว่า 10 เป็นbalanced(สมดุล) 10~25 เป็นslight(เล็กน้อย) เกิน 25 เป็นclear(ชัดเจน) - แนวโน้มฝั่งซาจู (
sajuLean): นำน้ำหนักของกฎที่ตรงกับก้านวันเกิด · ธาตุที่มากหรือน้อย (ตามการตัดสินของเอนจิน) · กลุ่มสิบเทพที่โดดเด่น (กลุ่มเดียวกัน 3 ตำแหน่งขึ้นไป) มาบวกแยกตามตัวอักษรในแต่ละแกน แล้วเลือกฝั่งที่มากกว่า หากเท่ากันหรือไม่มีกฎที่ตรงจะเป็นbalancedID กฎที่ตรงอยู่ในruleIds·matchedRules - การเปรียบเทียบ (
comparison): หากทิศทางเดียวกันเป็นrelation: "same"("ทิศทางเดียวกับซาจู") หากต่างกันเป็น"different"("พัฒนาด้านที่ต่างจากซาจู") หากฝั่งใดฝั่งหนึ่งเป็นbalancedจะเป็น"neutral"ประโยค (text) ตอนนี้ออกมาเป็นภาษาเกาหลีเท่านั้นlangมีผลเฉพาะกับbirthHour.note - ไม่ทราบเวลาเกิด: หากตัด
hourออก จะคำนวณด้วยเกณฑ์เดียวกับอัตลักษณ์ซาจู และแนบbirthHourหากเป็นเกณฑ์ 3 เสาwonkuk.hourเป็นnullและpillarCountเป็น 3 - กฎข้อควรระวัง:
caveatRuleId(R-MBTI-CAVEAT-001) และcaveatsมีข้อความแจ้งว่า "เป็นการตีความสมัยใหม่ ไม่ใช่การตัดสิน" โปรดแสดงบนหน้าจอด้วย - endpoint ในบันทึกการใช้งาน:
saju-mbti
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/saju-mbti \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "year": 1990, "month": 5, "day": 15, "hour": 12, "minute": 0, "timezone": "Asia/Seoul", "gender": "male", "mbti": "INFJ" }'
ตัวอย่างการตอบกลับ (ตัดตอน ผลลัพธ์จริงของเอนจิน)
{
"success": true,
"data": {
"wonkuk": {
"year": { "cheongan": "경", "jiji": "오", "ohaeng": "금" },
"month": { "cheongan": "신", "jiji": "사", "ohaeng": "금" },
"day": { "cheongan": "경", "jiji": "진", "ohaeng": "금" },
"hour": { "cheongan": "임", "jiji": "오", "ohaeng": "수" }
},
"pillarCount": 4,
"dayMaster": "경",
"strength": "신약",
"ohaengCount": { "목": 0, "화": 3, "토": 1, "금": 3, "수": 1 },
"ohaengState": { "목": "lack", "화": "balanced", "토": "lack", "금": "balanced", "수": "lack" },
"dominantSipseong": ["관성"],
"mbti": {
"type": "INFJ",
"source": "letters",
"axes": {
"E_I": { "value": 25, "letter": "I", "band": "slight" },
"S_N": { "value": 25, "letter": "N", "band": "slight" },
"T_F": { "value": 25, "letter": "F", "band": "slight" },
"J_P": { "value": 75, "letter": "J", "band": "slight" }
}
},
"sajuLean": {
"E_I": { "lean": "balanced", "weights": { "E": 1, "I": 1 }, "ruleIds": ["R-MBTI-OHAENG-010", "R-MBTI-STRENGTH-002"] },
"S_N": { "lean": "S", "weights": { "S": 1 }, "ruleIds": ["R-MBTI-OHAENG-006"] },
"T_F": { "lean": "T", "weights": { "T": 2 }, "ruleIds": ["R-MBTI-STEM-007"] },
"J_P": { "lean": "J", "weights": { "P": 1, "J": 2 }, "ruleIds": ["R-MBTI-OHAENG-008", "R-MBTI-SIPSEONG-002"] }
},
"comparison": [
{ "axis": "E_I", "label": "에너지 방향(E·I)", "user": "I", "userBand": "slight", "saju": "balanced", "relation": "neutral",
"text": "에너지 방향(E·I): 사주에서는 어느 한쪽으로 기우는 경향이 뚜렷하지 않아요. 입력은 I 쪽이에요." },
{ "axis": "S_N", "label": "인식 방식(S·N)", "user": "N", "userBand": "slight", "saju": "S", "relation": "different",
"text": "인식 방식(S·N): 사주와 다른 면을 키운 것으로 볼 수 있어요. 사주는 S 쪽 경향이 있고, 입력은 N 쪽이에요." },
{ "axis": "T_F", ... },
{ "axis": "J_P", "label": "생활 방식(J·P)", "user": "J", "userBand": "slight", "saju": "J", "relation": "same",
"text": "생활 방식(J·P): 사주와 같은 방향이에요. 사주에서 보이는 J 쪽 경향이 입력에도 드러나요." }
],
"matchedRules": [
{ "id": "R-MBTI-STEM-007", "statement": "庚 일간은 단단한 쇠의 기운으로 읽혀, 기준을 세워 따져 보고 결단하는 쪽(T)으로 기울기 쉬운 경향이 있어요." },
...
],
"caveats": [ { "id": "R-MBTI-CAVEAT-001", "statement": "사주와 MBTI를 잇는 이 해석은 고전 명리 이론이 아니라 현대의 해석 관행이에요. ..." }, ... ],
"caveatRuleId": "R-MBTI-CAVEAT-001",
"interim": false,
"kbStatus": "literature",
"kbVersion": "2026.10.16-2",
"engineVersion": "saju-mbti-1"
}
}
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | (การตรวจเนื้อหา) | ไม่มี mbti ไม่ใช่ 4 ตัวอักษร ค่าแกนไม่ใช่จำนวนเต็ม 0~100 หรือมีคีย์ที่ไม่รู้จัก |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
| 404 | saju_mbti_not_enabled | เมื่อฝ่ายปฏิบัติการปิดฟีเจอร์ |
API ดวงวันนี้
POST /api/v1/partners/v1/today
นำเสาประจำวันของวันที่ระบุ (ค่าเริ่มต้น: วันนี้ตามเวลาเกาหลี) มาเทียบกับซาจูของเรา แล้วคืนสรุปประจำวัน (เสาประจำวัน · สิบเทพของวันนี้ · MBTI โหมดวันนี้ · คะแนนกระแสของปีนี้ · ดาวพิเศษที่ปรากฏ · สามภัย) และดวงวันนี้ (ความสัมพันธ์เสาประจำวัน×ก้านวันเกิด สีนำโชค · อาหาร · คีย์เวิร์ด ช่วงเวลาดี · ช่วงเวลาที่ควรเลี่ยง กิจกรรมแนะนำ ข้อความหนึ่งบรรทัด) เป็นการคำนวณเดียวกับการ์ด "วันนี้" ในหน้าแรกของแอป INTA นอกจากนี้จะมีความเหมาะสมของกิจกรรม (taskAffinity) และกระแสวันนี้หนึ่งบรรทัด (summary.daily_flow) แนบมาเสมอ หากส่งอุณหภูมิ · สภาพอากาศ จะเพิ่มการแต่งกายวันนี้ (fashion) และหาก mbtiBehavior: true จะเพิ่มรูปแบบพฤติกรรม MBTI โหมดวันนี้ (mbtiBehavior)
พารามิเตอร์คำขอ
รับข้อมูลการเกิดและตัวเลือกเสริม (lang · จันทรคติ · พิกัด · zaSiRule ฯลฯ) เหมือน API ปฏิทินหมื่นปี รหัสก้าน-กิ่ง · ธาตุทั้งห้าในการตอบกลับ (summary.day_master · ilju ฯลฯ) เป็นฮันกึลไม่ว่าภาษาใด — ตารางค่ารหัส หากไม่รู้จัก timezone การตอบกลับจะมี warnings แนบมาเหมือนปฏิทินหมื่นปี เพิ่มเติม:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
date | string | วันที่ต้องการดู YYYY-MM-DD (1900-2100) หากละไว้คือวันนี้ตามเวลาเกาหลี | |
temperatureC | number | อุณหภูมิปัจจุบัน (℃, −40~50) หากส่งมา การตอบกลับจะมี fashion (การแต่งกายช่วงเช้า · กลางวัน · เย็น) หากละไว้จะไม่มี fashion (ไม่ประมาณเอง) | |
weather | string | สภาพอากาศ: clear · cloudy · rain · snow · storm | |
humidity | number | ความชื้นสัมพัทธ์ (%, 0~100) ต้องส่งครบทั้งสามค่า temperatureC · weather · humidity จึงจะมี fashion.mood (ความเห็นเรื่องอากาศหนึ่งบรรทัดตามช่วงเวลา) | |
mbtiBehavior | boolean | หากเป็น true จะแนบรูปแบบพฤติกรรม (mbtiBehavior) ของ summary.today_mbti ค่าเริ่มต้น false |
ตัวอย่างคำขอ
{
"year": 1990, "month": 5, "day": 15, "hour": 12, "minute": 0,
"timezone": "Asia/Seoul", "gender": "male",
"date": "2026-10-10",
"temperatureC": 16, "weather": "cloudy", "humidity": 60,
"mbtiBehavior": true
}
ตัวอย่างการตอบกลับ (ผลลัพธ์จริงของเอนจิน ละบางส่วน)
{
"success": true,
"data": {
"date": "2026-10-10",
"summary": {
"ilju": "경진",
"day_master": "경",
"gyeokguk": "비견격",
"gyeokguk_reason": "월지 사 중기(경) 투간 [연간=경]",
"inferred_mbti": "ESFJ",
"today_mbti": "ESFJ",
"current_mbti": "ESFJ",
"strength_label": "신약",
"yongshin": "수",
"today_date": "2026-10-10",
"today_ganji": "정사",
"today_day_ohaeng": "화",
"today_sipsin": "정관",
"flow_score": 60,
"flow_tier": "good",
"top_favored_task_type": "routine",
"top_caution_task_type": "movement",
"active_sinsal_names": ["학당", "암록", "복성귀인", "화개살", "자형(오오)"],
"in_samjae": false,
"daily_flow": "오늘(정사일) 화 에너지가 흘러 소통·확장에 유리해."
},
"omen": {
"relation": { "type": "GEUK", "label": "조율의 날" },
"color": { "name": "주황", "hex": "#FFA45B", "ohaeng": "화" },
"food": "고추장비빔밥",
"keyword": "공개",
"message": "표현하고 싶은 마음과 주변 반응이 엇갈릴 수 있는 날이에요. 즉흥적인 말보다 한 박자 늦춘 표현이 좋아요.",
"luckyHour": "오전 11시 ~ 오후 1시",
"avoidHour": "밤 11시 이후",
"activity": "칭찬 먼저 하기"
},
"taskAffinity": [
{ "taskType": "focus", "score": -0.25, "verdict": "neutral",
"reason": "길 십신 2개 일치 · 흉 십신 2개 일치 · 일진 천간 정관(흉) · 일진 지지 편관(흉) · 천간합" },
{ "taskType": "creative", "score": -0.75, "verdict": "caution", "reason": "..." },
...,
{ "taskType": "routine", "score": 0.25, "verdict": "favored",
"reason": "길 십신 4개 일치 · 일진 천간 정관(흉) · 일진 지지 편관(흉) · 천간합" }
],
"fashion": {
"temperatureC": 16, "tempBand": "T3",
"main": "버건디 자켓", "accent": "가죽 벨트",
"colorAttachLabel": "반지나 메탈 액세서리에",
"byTime": {
"morning": { "main": "버건디 자켓", "accent": "가죽 벨트", "tempBand": "T3" },
"noon": { ... }, "evening": { ... }
},
"mood": {
"feelsLikeC": 16, "tempBand": "jacket", "humidBand": "normal", "weatherKey": "cloudy",
"morning": { "headline": "흐린 자켓 새벽", "body": "햇볕 없어 살짝 서늘. 자켓 한 벌.", "carry": [] },
"noon": { ... }, "evening": { ... }
}
},
"mbtiBehavior": {
"mbti": "ESFJ",
"headline": "협력·돌봄",
"actions": ["약속·일정 챙기기 좋은 날", "주변에 도움 줄 수 있는 일 1개", "집·환경 정돈", "내 페이스도 지키기 — 다 떠안지 않기"],
"closingLine": "주변과 결이 맞아 흐름이 부드러워요."
}
}
}
omen.relation.typeคือรหัสความสัมพันธ์ระหว่างก้านวันเกิดของเรากับก้านฟ้าของเสาประจำวันนั้น:HAB(รวม) ·SAENG(ส่งเสริม) ·SAME(ธาตุเดียวกัน) ·GEUK(ข่ม) ·CHUNG(ปะทะ)labelคือชื่อที่คนอ่านได้flow_score·flow_tierคือกระแสของปีนั้น (ดวงรายปี) ส่วนtoday_mbtiคือ "โหมดวันนี้" ที่นำ MBTI ซาจูของเรามาบวกกับเสาประจำวันนั้นtaskAffinity: ความเหมาะสมวันนี้ของกิจกรรม 7 ประเภท (focus·creative·contact·finance·organize·movement·routine) แต่ละรายการ{ taskType, score, verdict, reason }verdictเป็นfavored·neutral·cautionลำดับเป็นลำดับของเอนจิน (ไม่ใช่เรียงตามคะแนน)summary.daily_flow: กระแสวันนี้หนึ่งบรรทัดsummary.samjae_label: ประเภท · ขั้นของสามภัยเมื่อเป็นปีสามภัย (หากไม่ใช่จะไม่มี)fashion: เฉพาะเมื่อส่งtemperatureCfashion.moodเฉพาะเมื่อส่งครบtemperatureC·weather·humiditymbtiBehavior: เฉพาะเมื่อmbtiBehavior: true(หากไม่มีรูปแบบ MBTI ของวันนั้นจะละไว้)- หากส่ง
lang(en/ja/th) สตริงของรูปแบบดวง · กระแสในสรุป ดวงวันนี้taskAffinity·daily_flow·samjae_label·fashion·mbtiBehaviorจะถูกแปลทั้งหมด หากละไว้หรือเป็นkoจะเป็นภาษาเกาหลี - ข้อมูลการเกิดเดียวกัน ·
dateเดียวกัน (และอินพุตสภาพอากาศเดียวกัน) ให้ผลเหมือนเดิมเสมอ หากไม่ทราบเวลาเกิดจะคำนวณตามเที่ยงวันและแนบbirthHourหากเป็นอินพุตจันทรคติจะมีlunarInputแนบมา
ราคา
- ₩10/ครั้ง คิดค่าบริการเฉพาะการเรียกที่สำเร็จ และการเรียกซ้ำด้วยอินพุตเดิมก็คิดค่าบริการแยกกัน (Idempotency)
- อินพุตผิดพลาด (400) · ยอดคงเหลือไม่พอ (402) · คำนวณล้มเหลว ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือ
today
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | today_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
API ทำนายฝัน
POST /api/v1/partners/v1/dream
ค้นหาคำสัญลักษณ์ (เช่น ทะเล ปลา) จากเรื่องความฝันที่ผู้ใช้ปลายทางเล่า แล้วคืนตามลำดับความโดดเด่น คำเหล่านี้ค้นจากคลังคำสัญลักษณ์ความฝันที่ HRUM สร้างขึ้นเอง (คำนามในชีวิตประจำวันกว่า 1,000 คำ พร้อมคำพ้องความหมาย · รูปผันคำ · ภาษาพูด) คลังคำมีแต่คำ ไม่มีความหมายการทำนายหรือการตัดสินดีร้าย ทุกคำที่คืนมาคือคำที่คำนั้นหรือคำพ้องความหมาย · รูปผันคำปรากฏจริงในเนื้อหาความฝัน
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
dream | string | ✓ | เรื่องความฝัน (สูงสุด 1,000 ตัวอักษร) |
feeling | string | อารมณ์ที่รู้สึกในความฝัน (สูงสุด 300 ตัวอักษร เช่น "무섭고 답답했어요" — "ทั้งกลัวทั้งอึดอัด") รวมกับเนื้อหาความฝันแล้วดึงแท็ก (ใช้ความยาวรวมได้ถึง 1,000 ตัวอักษร) | |
lang | string | ภาษาของการตอบกลับ ปัจจุบันรองรับเฉพาะ ko (พจนานุกรมเป็นภาษาเกาหลีเท่านั้น) ค่าอื่นได้ 400 | |
includeNegative | boolean | จะรวมบันทึกการตัดสินในทางร้าย (ความตาย · โรค · การสูญเสีย ฯลฯ) ในหลักฐานจากตำราโบราณหรือไม่ ค่าเริ่มต้น false จะถูกละเว้นก่อนเปิดหลักฐานจากตำราโบราณ |
ตัวอย่างคำขอ
{
"dream": "바다에서 커다란 물고기를 두 손으로 잡는 꿈을 꿨어요"
}
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"lang": "ko",
"mode": "glossary",
"items": [
{ "keywords": ["바다"], "score": 1 },
{ "keywords": ["물고기"], "score": 0.979 },
{ "keywords": ["손"], "score": 0.749 }
]
}
}
itemsสูงสุด 40 รายการ หนึ่งรายการ =keywords(คำพื้นฐานหนึ่งคำในคลังคำสัญลักษณ์ เช่น "치아" (ฟัน) · "앞니" (ฟันหน้า) เป็น["이빨"]) +scoreคำเดียวกันจะออกมาเพียงครั้งเดียว ลำดับเรียงตามความโดดเด่นในความฝัน (ยิ่งปรากฏก่อน ยิ่งปรากฏหลายครั้ง ยิ่งเป็นคำที่เฉพาะเจาะจง ยิ่งอยู่หน้า)scoreอยู่ระหว่าง 0~1 และเท่าเดิมหรือลดลงตามลำดับรายการ (1 = สัญลักษณ์ที่โดดเด่นที่สุดในความฝันนี้)mode:glossary(พบในคลังคำสัญลักษณ์) ·none(ไม่พบสัญลักษณ์)feelingก็ค้นหาพร้อมกับเนื้อหาความฝัน- อินพุตเดียวกันให้ผลเดียวกัน คำนวณทันทีภายในเซิร์ฟเวอร์โดยไม่มีการเรียกภายนอก
- ไม่มีประโยคการอ่านความหมาย หากต้องการคำอธิบายเพื่อแสดงแก่ผู้ใช้ปลายทาง ให้ส่งเนื้อหาความฝันและคำเหล่านี้ไปยัง AI อ่านดวงซาจู (
only: "dream") หรือเป็นอินพุตของ LLM - เปลี่ยนแปลง 2026-10-11: ฟิลด์
title·meaningในการตอบกลับเดิมถูกยกเลิกและเปลี่ยนเป็นkeywordsในวันเดียวกัน แหล่งที่มาของคำสัญลักษณ์เปลี่ยนเป็นคลังคำสัญลักษณ์ของ HRUM เอง แต่ละรายการจึงมีคำเดียว และค่าmodeเหลือสองค่าคือglossary·none(ค่าเดิมtags·fallback_charจะไม่ออกมาอีก)
ราคา
- ₩30/ครั้ง คิดค่าบริการเฉพาะเมื่อพบอย่างน้อยหนึ่งรายการ หากผลว่าง (
items: []) จะเป็น ₩0 การเรียกซ้ำด้วยอินพุตเดิมก็คิดค่าบริการแยกกัน (Idempotency) - อินพุตผิดพลาด (400) · ยอดคงเหลือไม่พอ (402) ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือ
dream
หลักฐานจากตำราโบราณ kbMatches
คืนกฎ KB การทำนายฝันที่ตรงกับสิ่งที่ปรากฏในเนื้อหาความฝัน (ท้องฟ้า งู ตลาด ฯลฯ) หลักฐานคือต้นฉบับตำราทำนายฝันโบราณที่เป็นงานสาธารณสมบัติ — ฉบับตุนหวง "Zhou Gong Jie Meng Shu" (P.3908 ศตวรรษที่ 10) และหมวดความฝันของ "Gujin Tushu Jicheng" เนื้อหาความฝันเดียวกันให้ผลเดียวกันเสมอ (กฎระดับตัวอักษรที่ไม่ใช้บริการแท็ก · LLM)
"kbMatches": [
{
"ruleId": "R-DREAM-DRAGON-002",
"area": "DRAGON",
"polarity": "positive",
"status": "verified",
"statement": "“주공해몽서”(돈황본 P.3908, 第十二 龍蛇章)는 뱀(虵=蛇)이 길에 있는 꿈(夢見虵當道者)에 대해 “大吉”라고 적는다(글자대로: 크게 길하다).",
"quote": {
"text": "夢見虵當道者大吉",
"sourceId": "SRC-DREAM-P3908",
"source": "“周公解夢書” (敦煌 P.3908)",
"location": "P.3908 第十二 龍蛇章 f09/左/行3下",
"foundAt": "dream-pd/dunhuang-p3908-bnf/P3908-TRANSCRIPTION-merged.md:198"
},
"caveatRuleIds": [],
"matchedTerms": ["구렁이", "길"]
}
]
statementเป็นประโยคที่บอกว่าต้นฉบับบันทึกไว้เช่นนั้น ไม่ใช่คำทำนายว่าความฝันบอกอนาคตquoteคือต้นฉบับหนึ่งบรรทัดที่เป็นหลักฐานและตำแหน่งpolarity: ตามส่วนการตัดสินในต้นฉบับpositive·negative·neutralnegative(บันทึกเรื่องความตาย · โรค · การสูญเสีย ฯลฯ) จะรวมเฉพาะเมื่อincludeNegative: truecaveatRuleIds: กฎข้อควรระวังที่เกี่ยวกับกฎนั้น (เช่น บันทึกเรื่องความตาย · โรคภัยคือR-DREAM-CAVEAT-002)- หากไม่มีกฎที่ตรงจะเป็นอาร์เรย์ว่าง การเรียกที่ไม่ถูกคิดค่าบริการ (เช่น การเรียกที่ได้
items: []เป็น ₩0) จะไม่มีแนบมา
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | dream_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
หาก dream ว่างหรือเกิน 1,000 ตัวอักษร จะได้ 400 ทั่วไป หากไม่พบสัญลักษณ์ ไม่ใช่ข้อผิดพลาด แต่ได้ 200 พร้อม items: [] (₩0)
API วัดโหงวเฮ้ง · ลายมือ
ไม่ต้องส่งรูปถ่าย เมื่อส่งพิกัด (ใบหน้า 478 จุด / มือ 21 จุด โพลีไลน์ของเส้นลายมือ) ที่ดึงด้วย MediaPipe บนอุปกรณ์ · เบราว์เซอร์ของพาร์ทเนอร์ เซิร์ฟเวอร์จะคำนวณคีย์การวัด (อัตราส่วน · มุม · โซน) ด้วยฟังก์ชันบริสุทธิ์เดียวกัน แล้วคืนกฎ KB โหงวเฮ้ง · ลายมือ (บันทึกจากต้นฉบับโบราณ) ที่ตรงกับค่านั้น ไม่ใช้ LLM และพิกัดเดียวกันให้ผลเดียวกันเสมอ โค้ดอ้างอิงสำหรับดึงพิกัด (MediaPipe บนเบราว์เซอร์ · Node · curl) อยู่ที่หน้าโค้ดอ้างอิง หากชื่อโมเดล · เวอร์ชัน · การนอร์มัลไลซ์ · จำนวนพิกัดต่างจากค่าด้านล่างแม้แต่อย่างเดียวจะได้ 400
POST /api/v1/partners/v1/face-measure
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
modelName, modelVersion | string | ✓ | โมเดลที่สร้างพิกัด หากอยู่นอกรายการที่อนุญาตจะได้ 400 MEASURE_MODEL_UNSUPPORTED / MEASURE_MODEL_VERSION_MISMATCH ปัจจุบัน: face_landmarker · float16/[email protected] |
normalization | string | ✓ | face-norm-1 |
landmarks | number[][] | ✓ | [x, y] หรือ [x, y, z] จำนวน 478 จุดพอดี (ค่าที่หารด้วยความกว้าง · ความสูงของภาพ −0.02~1.02) |
imageWidth, imageHeight | number | ✓ | ขนาดเป็นพิกเซล |
hairline | [number, number] | จุดแนวไรผมกลางใบหน้าหนึ่งจุด เซิร์ฟเวอร์ไม่ประมาณเอง — หากไม่มี คีย์ที่เกี่ยวกับส่วนบนของใบหน้า (upper court) จะเป็น null (สาเหตุ hairline_missing) แนะนำให้ผู้ใช้แตะจุดเริ่มของเส้นผมเหนือหน้าผากเป็นอินพุต (โมเดลแบ่งส่วนเส้นผมใช้เพื่ออ้างอิงเท่านั้น) | |
quality | object | yawDeg · pitchDeg · rollDeg · blendshapes (ชื่อสัมประสิทธิ์ MediaPipe→คะแนน) ต้องส่งมาจึงจะตรวจคุณภาพได้ | |
includeNegative | boolean | จะรวมบันทึกการตัดสินในทางร้าย (polarity negative) หรือไม่ ค่าเริ่มต้น false (ชื่อ · ความหมายเดียวกับทำนายฝัน) |
POST /api/v1/partners/v1/palm-measure
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
modelName, modelVersion | string | ✓ | ปัจจุบัน: hand_landmarker · float16/[email protected] |
normalization | string | ✓ | palm-norm-1 |
landmarks | number[][] | ✓ | 21 จุดพอดี |
imageWidth, imageHeight | number | ✓ | ขนาดเป็นพิกเซล |
handedness | string | ✓ | left | right — มือจริงของผู้ถูกถ่าย (ให้ผู้ใช้เลือก) |
mirrored | boolean | หากเป็นภาพกลับซ้าย-ขวา (พรีวิวเซลฟี) ให้เป็น true | |
creases | object[] | โพลีไลน์ของเส้นลายมือ (สูงสุด 64 เส้น เส้นละ 2~512 จุด) รายการ: points (✓), label (life · head · heart · fate · sun · mercury · simian · unknown), kind (segment | branch), autoLabel หากไม่มี คีย์ที่เกี่ยวกับเส้นจะเป็น null (creases_missing) | |
autoLabel | boolean | ตั้งชื่อเส้นที่ไม่มีชื่อทั้งหมดด้วยฮิวริสติกกลางของเซิร์ฟเวอร์ หากต้องการใช้กับเส้นเดียว ให้ใช้ autoLabel ของรายการนั้น label ที่ตั้งเองมีลำดับความสำคัญสูงกว่าเสมอ | |
includeNegative | boolean | เหมือนใบหน้า ค่าเริ่มต้น false |
- ต่อชิ้นส่วนเส้นก่อนส่ง เซิร์ฟเวอร์ไม่ต่อชิ้นส่วนให้ และฮิวริสติกจะตั้งชื่อเพียงชิ้นเดียวต่อเส้น ชิ้นที่ขาดตรงจุดตัดกับเส้นอื่น (เช่น เส้นหัวใจที่พบกับเส้นวาสนา) ต้องต่อก่อนส่งเหมือน
stitch_creases.pyในโค้ดอ้างอิงจึงจะได้ชื่อ ส่วนรอยขาดจริงที่มองเห็นได้ให้คงไว้ตามเดิม (จำนวนที่ขาดนับด้วยคีย์breaks)
ตัวอย่างคำขอ (ใบหน้า ย่อ)
{
"modelName": "face_landmarker",
"modelVersion": "float16/[email protected]",
"normalization": "face-norm-1",
"landmarks": [[0.5012, 0.3121, -0.031], … 478개 …],
"imageWidth": 1080,
"imageHeight": 1350,
"hairline": [0.501, 0.182],
"quality": { "yawDeg": 2.1, "pitchDeg": -3.4, "blendshapes": { "eyeBlinkLeft": 0.05, "jawOpen": 0.02 } }
}
ตัวอย่างการตอบกลับ (ตัดตอนส่วนต้น)
{
"success": true,
"data": {
"normalization": "face-norm-1",
"keys": { "face.thirds.upper_ratio": 0.3333, "face.brow.length_vs_eye": 1.625, "face.brow.outer_overhang": 0.1648, … },
"reasons": {},
"quality": { "rollDeg": 0, "iodPx": 158, "flags": [] },
"kbMatches": [
{
"ruleId": "R-FACE-PALACE-031",
"area": "PALACE",
"kind": "interpretation",
"polarity": "positive",
"status": "verified",
"statement": "“古今圖書集成” 相術部彙考 “十二宮訣” 兄弟는 눈썹이 눈보다 길게 지나가면(眉長過目) …라고 적는다 …",
"quote": { "text": "眉長過目,三四兄弟", "sourceId": "SRC-FACE-HUIKAO", "source": "…", "location": "…", "foundAt": "…" },
"caveatRuleIds": ["R-FACE-CAVEAT-001"],
"matchedConditions": [{ "key": "face.brow.outer_overhang", "op": "gt", "value": 0, "actual": 0.1648 }]
}
]
}
}
keys: คีย์การวัดทั้งหมด (นิยามคีย์ · สูตรคำนวณ · ความน่าเชื่อถืออยู่ในเอกสารตารางคีย์) หากให้ค่าไม่ได้จะเป็นnullและมีสาเหตุในreasons:hairline_missing·blink·smile·jaw_open·finger_bent·creases_missing·back_of_hand(ภาพหลังมือ — เฉพาะคีย์ที่เกี่ยวกับเส้น) ฯลฯmissingSections: จำนวนคีย์การวัดที่มีค่าเป็นnull(คีย์และสาเหตุอยู่ในkeys·reasons) ถ้าเป็น 0 แสดงว่าได้ครบทุกคีย์kbMatches: รวมเฉพาะกฎที่ต้นฉบับให้ตัวเลข · การเปรียบเทียบไว้โดยตรง กฎที่ตัดสินด้วยค่าเกณฑ์ที่เรากำหนดเองเท่านั้นจะยังไม่รวม เพราะยังไม่ได้วัดหลักฐานจริง (PoC)statementเป็นบันทึกว่าต้นฉบับเขียนไว้เช่นนั้น ไม่ใช่คำทำนาย · การวินิจฉัยnegativeเฉพาะเมื่อincludeNegative: true- คุณภาพ: หากหันหน้า · ก้มหน้าเกิน 10° (
MEASURE_QUALITY_POSE) หรือใบหน้าเล็กเกินไป (MEASURE_QUALITY_FACE_SIZE) คำขอทั้งหมดจะได้ 400 — แนะนำให้ถ่ายใหม่ การหลับตา · ยิ้ม · อ้าปาก ไม่ได้ 400 แต่เฉพาะคีย์ที่เกี่ยวข้องจะเป็นnull - อินพุตผิดพลาดจะคืน 400 พร้อมรหัส (
MEASURE_LANDMARK_COUNT·MEASURE_COORD_RANGE·MEASURE_COORD_NAN·MEASURE_CREASE_LIMITฯลฯ) ข้อความข้อผิดพลาดมีเพียงหมายเลขจุด ไม่มีค่าพิกัด - เมื่อแสดงบันทึกในทางร้าย (
includeNegative: true):statementเป็นบันทึกว่าต้นฉบับเขียนไว้เช่นนั้น ให้สื่อสารกับผู้ใช้ว่า "มีบันทึกว่ามีแนวโน้มเช่นนี้ + อาจรับมือได้แบบนี้" และอย่าเปลี่ยนเป็นคำที่ดูถูกคนหรือตีตราบุคลิกภาพ
รหัสข้อผิดพลาด
| HTTP | code | ความหมาย |
|---|---|---|
| 400 | MEASURE_MODEL_UNSUPPORTED | modelName ไม่อยู่ในรายการที่อนุญาต |
| 400 | MEASURE_MODEL_VERSION_MISMATCH | modelVersion ไม่อยู่ในรายการที่อนุญาต (ปัจจุบันเฉพาะ float16/[email protected]) |
| 400 | MEASURE_NORMALIZATION_MISMATCH | normalization ไม่ใช่ face-norm-1 / palm-norm-1 |
| 400 | MEASURE_LANDMARK_COUNT | จำนวนพิกัดไม่ใช่ใบหน้า 478 / มือ 21 |
| 400 | MEASURE_LANDMARK_SHAPE · MEASURE_COORD_NAN · MEASURE_COORD_RANGE · MEASURE_IMAGE_SIZE · MEASURE_DEGENERATE | ข้อผิดพลาดของรูปแบบจุด · ตัวเลข · ช่วง (−0.02~1.02) · ขนาดภาพ |
| 400 | MEASURE_HANDEDNESS · MEASURE_CREASE_LIMIT · MEASURE_CREASE_SHAPE · MEASURE_CREASE_LABEL | อินพุตมือ · เส้นลายมือผิดพลาด |
| 400 | MEASURE_QUALITY_POSE · MEASURE_QUALITY_FACE_SIZE | หันหน้าเกิน 10° · ใบหน้าเล็กเกินไป — ถ่ายใหม่ |
| 400 | (ข้อผิดพลาดการตรวจสอบ) | ส่งฟิลด์ที่ไม่มีในเอกสาร — ส่งเฉพาะฟิลด์ที่อนุญาต |
| 402 | INSUFFICIENT_BALANCE | ยอดเครดิตคงเหลือไม่พอ |
| 404 | face_measure_not_enabled · palm_measure_not_enabled | ฟีเจอร์ที่ยังไม่เปิด |
การตอบกลับข้อผิดพลาดทั้งหมดไม่คิดค่าบริการ
ข้อมูลส่วนบุคคล
- ไม่รับรูปถ่าย รูปถ่ายถูกแปลงเป็นพิกัดบนอุปกรณ์ของผู้ใช้ และ API ได้รับเพียงพิกัด
- ไม่เก็บพิกัด พิกัดเป็นข้อมูลเรขาคณิตของใบหน้า · มือ เซิร์ฟเวอร์จึงใช้เฉพาะในหน่วยความจำระหว่างประมวลผลคำขอ และไม่ทิ้งไว้ในบันทึก · DB · ข้อความข้อผิดพลาด บันทึกการใช้งานเก็บเพียง endpoint · สถานะ · จำนวนเงิน
- ความยินยอมของผู้ใช้ปลายทาง พาร์ทเนอร์ต้องเป็นผู้ขอรับ
- MediaPipe ที่โค้ดอ้างอิงใช้เป็นสัญญาอนุญาต Apache-2.0 และอาจส่งสถิติการใช้งาน เมื่อนำไปใส่ในผลิตภัณฑ์ ให้เผยแพร่ประกาศสัญญาอนุญาตไปด้วยและระบุไว้ในนโยบายความเป็นส่วนตัว
ราคา
- วัดโหงวเฮ้ง ₩30 /ครั้ง วัดลายมือ ₩30 /ครั้ง (ไม่รวม VAT · รวม VAT ₩33)
- คิดค่าบริการเฉพาะเมื่อได้คีย์การวัดอย่างน้อยหนึ่งคีย์ หากไม่มีคีย์การวัดเลยเป็น ₩0 ข้อผิดพลาดอินพุต · คุณภาพ (400) · ยอดคงเหลือไม่พอ (402) · ยังไม่เปิด (404) ก็ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือ
face-measure/palm-measure - ในการวัดลายมือ หากตัดสินว่าเป็นภาพหลังมือ (
back_of_handในquality.flags) ทุกคีย์จะเป็นnull(สาเหตุback_of_hand) กฎ KB ก็ว่าง และไม่คิดค่าบริการ (₩0) ส่งใหม่ด้วยภาพด้านฝ่ามือและhandedness·mirroredที่ถูกต้อง การตัดสินหลังมือใช้ทิศทางการหมุนของพิกัดข้อมือ · โคนนิ้วชี้ · โคนนิ้วก้อย เทียบกับhandedness·mirrored - แม้บางคีย์เป็น
nullราคาก็เท่าเดิม จำนวนคีย์ที่ขาดแจ้งในmissingSections
API อ่านโหงวเฮ้ง · ลายมือ (จากรูปถ่าย)
อ่านโหงวเฮ้งจากรูปใบหน้าหนึ่งรูป และอ่านลายมือจากรูปฝ่ามือหนึ่งรูป รูปถ่ายใช้เฉพาะในหน่วยความจำของเซิร์ฟเวอร์และไม่เก็บไว้ สำหรับโหงวเฮ้ง แทนรูปถ่ายจะส่งพิกัด (landmarks) เดียวกับการวัดโหงวเฮ้งก็ได้ — จากนั้นจะหาคีย์การวัดและกฎ KB โดยไม่ใช้รูปถ่าย และ AI จะเขียนคำอธิบายด้วยภาษาง่ายๆ ให้แต่ละกฎ (การอ่านโหงวเฮ้งรวมคำอธิบายจาก AI เสมอ หากต้องการเฉพาะการวัดโดยไม่ใช้ AI ให้ใช้การวัดโหงวเฮ้ง) ผลลัพธ์คือการอ่านโหงวเฮ้ง · ลายมือแบบดั้งเดิมเพื่อความบันเทิงและการอ้างอิง ไม่ใช่การตัดสินข้อเท็จจริงหรือการวินิจฉัย
ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี แม้ส่ง lang อื่นก็ตอบเป็นภาษาเกาหลี (lang ในการตอบกลับเป็น "ko" เสมอ)
POST /api/v1/partners/v1/face-reading
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
image | object | อย่างใดอย่างหนึ่ง | { data, mimeType } — data คือ base64 ของไบต์รูปถ่าย (ไม่เกิน 8MB หลังถอดรหัส) mimeType คือ image/jpeg · image/png · image/webp รูปแบบจะถูกตรวจซ้ำจากไบต์ (หากไม่ตรงได้ 400) |
landmarks | object | อย่างใดอย่างหนึ่ง | เนื้อหาคำขอของการวัดโหงวเฮ้งตามเดิม (modelName · modelVersion · normalization · landmarks 478 จุด · imageWidth · imageHeight · hairline · quality · includeNegative) |
consent | object | ✓ หากเป็นรูปถ่าย | ความยินยอมในการประมวลผลรูปถ่าย — ดูอ็อบเจกต์ความยินยอมด้านล่าง |
llm | boolean | ไม่ต้องส่งก็ได้ — รวมคำอธิบายจาก AI เสมอ หากส่ง false จะได้ 400 USE_FACE_MEASURE (การวัดโดยไม่ใช้ AI คือการวัดโหงวเฮ้ง) | |
lang | string | รับ ko · en · ja · th แต่ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี (lang ในการตอบกลับ = "ko") | |
endUserId | string | ID ผู้ใช้ปลายทางที่พาร์ทเนอร์ใช้ (สูงสุด 255 ตัวอักษร) บันทึกไว้เฉพาะในบันทึกการใช้งาน |
ส่ง image และ landmarks อย่างใดอย่างหนึ่งเท่านั้น หากส่งทั้งสองหรือไม่ส่งเลยจะได้ 400 READING_INPUT_ONE_OF
ตัวอย่างคำขอ (โหงวเฮ้ง รูปถ่าย)
{
"image": { "data": "/9j/4AAQSkZJRgABAQ…(base64)", "mimeType": "image/jpeg" },
"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" },
"lang": "ko",
"endUserId": "member-1024"
}
POST /api/v1/partners/v1/palm-reading
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
image | object | ✓ | รูปด้านฝ่ามือหนึ่งรูป รูปแบบ · ขนาดเหมือนโหงวเฮ้ง |
consent | object | ✓ | อ็อบเจกต์ความยินยอม |
creases | object[] | เส้นลายมือที่ผู้ใช้วาดตามบนรูปถ่าย (สูงสุด 16 เส้น) รายการ: line (life · head · heart · fate · sun · mercury · simian · unknown), points ([x, y] 2~256 จุด 0~1 โดยนับจากมุมซ้ายบนของรูป) ใช้เป็นข้อมูลอ้างอิงหลักในการหาตำแหน่งเส้น | |
lang | string | เหมือนโหงวเฮ้ง (ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี) | |
endUserId | string | เหมือนโหงวเฮ้ง |
ตัวอย่างคำขอ (ลายมือ เส้นที่วาดตาม)
{
"image": { "data": "/9j/4AAQSkZJRgABAQ…(base64)", "mimeType": "image/jpeg" },
"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" },
"creases": [
{ "line": "life", "points": [[0.42, 0.38], [0.36, 0.52], [0.34, 0.71]] },
{ "line": "heart", "points": [[0.78, 0.33], [0.6, 0.31], [0.47, 0.34]] }
]
}
อ็อบเจกต์ความยินยอม consent
ตัวอย่าง: "consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" }
photo: ต้องเป็นtrue— หมายถึงผู้ใช้ยินยอมให้ประมวลผลรูปถ่ายversion: เวอร์ชันของข้อความขอความยินยอมที่พาร์ทเนอร์แสดง (1~40 ตัวอักษร)subject:end_user(รูปของผู้ใช้เอง) ·third_party(รูปของคนอื่น — พาร์ทเนอร์ต้องขอความยินยอมจากบุคคลนั้นด้วย)- หากไม่มีหรือค่าไม่ถูกต้องจะได้ 400
CONSENT_REQUIREDบันทึกการใช้งานเก็บเพียงversionและsubject
การประมวลผลรูปถ่าย
- รูปถ่ายใช้เฉพาะในหน่วยความจำระหว่างประมวลผลคำขอ ไม่ทิ้งไว้ในดิสก์ · DB · บันทึก · ที่เก็บไฟล์ และไม่สร้างหรือเก็บค่าลักษณะเฉพาะของใบหน้า · มือ (เทมเพลต · เอมเบดดิง) ไม่ระบุตัวตนว่าเป็นใคร และไม่นำไปเทียบกับรูปอื่น
- ก่อนส่งไปยังโมเดลภายนอก จะลบเมทาดาทาอย่าง EXIF (รวมตำแหน่ง · ข้อมูลอุปกรณ์) · XMP · ICC และสร้างใหม่เป็น JPEG ด้านยาวไม่เกิน 1600px ส่วน WebP จะลบเฉพาะเมทาดาทาแล้วส่งตามเดิม จึงรับเฉพาะด้านยาวไม่เกิน 1600px (ใหญ่กว่านั้นได้ 413 — ย่อขนาดหรือส่งเป็น JPEG · PNG)
- รูปหนึ่งรูปเรียกโมเดลภายนอกสองครั้ง: จำแนกรูปก่อน (ใช่ใบหน้า · ฝ่ามือหรือไม่ เป็นคนเดียวหรือไม่ ดูเหมือนผู้เยาว์หรือไม่ คุณภาพของภาพ) แล้วจึงเขียนคำอ่านเฉพาะเมื่อผ่าน ทั้งสองการเรียกเป็น
store: false - ไม่อ่านรูปที่ดูเหมือนผู้เยาว์ (อายุต่ำกว่า 18 ปี) รูปที่มีหลายคน · สองมือขึ้นไป รูปที่ไม่ใช่ใบหน้า · ฝ่ามือก็เช่นกัน (400
IMAGE_NOT_ALLOWED) รูปหลังมือได้ 400PALM_NOT_DETECTEDสำหรับลายมือ ให้ถ่ายโดยมีฝ่ามือเพียงข้างเดียวในภาพ แม้ปลายนิ้วของอีกมือโผล่มาเพียงเล็กน้อย ก็อาจถูกมองว่าเป็นสองมือและถูกปฏิเสธ - โมเดลภายนอก: ส่งไปยัง OpenAI (สหรัฐอเมริกา) ส่งด้วย
store: falseOpenAI ไม่ใช้อินพุต API ในการฝึก และเก็บไว้สูงสุด 30 วันเพื่อเฝ้าระวังการใช้ในทางที่ผิดแล้วลบmeta.processingในการตอบกลับมีเนื้อหาเดียวกันในรูปแบบคงที่ - คำอ่านจะไม่มีเรื่องสุขภาพ · โรค · อายุขัย เชื้อชาติ · ชาติพันธุ์ · สัญชาติ · สีผิว อายุ อาชญากรรม · ศีลธรรม ตัวตน · คนที่หน้าคล้าย รสนิยมทางเพศ · ศาสนา และการฟันธงบุคลิกภาพ · ชะตากรรม ป้องกันด้วยคำสั่งต่อโมเดล และกรองประโยคเหล่านั้นอีกครั้งในการตอบกลับ
meta.processing ในการตอบกลับเป็นรูปแบบคงที่ (เมื่ออ่านจากรูปถ่าย):
"processing": {
"provider": "OpenAI",
"model": "gpt-5.6-luna",
"region": "US",
"store": false,
"retention": "API 입력은 학습에 쓰지 않음, 오남용 감시로 최대 30일 보관 뒤 삭제",
"imageStored": false
}
การตอบกลับที่ไม่ได้เรียกโมเดลภายนอก (กรณีที่ landmarks ไม่มีคีย์การวัดหรือบันทึก KB ที่ตรงเลย จึงจบที่ ₩0) จะมี provider · model · region · store · retention เป็น null และ imageStored เป็น false
ตัวอย่างการตอบกลับ (โหงวเฮ้ง รูปถ่าย)
{
"success": true,
"data": {
"items": [
{
"key": "forehead",
"label": "이마",
"observation": "이마가 넓고 둥글게 보여요.",
"reason": "넓은 이마는 생각을 넓게 펼치는 쪽으로 읽혀요. 떠오른 계획을 글로 정리해 두면 장점이 더 살아나요."
},
{
"key": "eyes",
"label": "눈",
"observation": "눈매가 길고 가로로 뻗어 있어요.",
"reason": "긴 눈매는 사람과 상황을 찬찬히 살피는 쪽으로 읽혀요."
}
],
"summary": "생각을 넓게 펼치고 찬찬히 살피는 인상으로 읽혀요.",
"lang": "ko",
"meta": {
"input": "image",
"processing": { "provider": "OpenAI", "model": "gpt-5.6-luna", "region": "US", "store": false, "retention": "API 입력은 학습에 쓰지 않음, 오남용 감시로 최대 30일 보관 뒤 삭제", "imageStored": false },
"disclaimer": "entertainment_reference",
"disclaimerText": "전통 관상·손금·성명학을 재미와 참고로 풀어 본 내용이에요. 사실 판단이나 진단이 아니에요.",
"kbRuleIds": []
}
}
}
items: รวมเฉพาะส่วนที่มองเห็นในรูปkeyของโหงวเฮ้ง:face_shape·forehead·eyebrows·eyes·nose·mouth·ears·chinkeyของลายมือ:hand_shape·fingers·life_line·head_line·heart_line·fate_line·sun_line·mountslabelมาเป็นภาษาเกาหลี- โหงวเฮ้งที่ส่งเป็น
landmarksจะได้ฟิลด์การตอบกลับของการวัดโหงวเฮ้ง (normalization·keys·reasons·quality·kbMatches·missingSections) มาด้วยชื่อเดียวกัน และitemsมีหนึ่งรายการต่อกฎ KB เหมือนการอ่านจากรูปlabelคือชื่อส่วน (คิ้ว · ตา · จมูก …)reasonคือประโยคคำอ่านที่ AI เขียนด้วยภาษาง่ายๆ และจะมีkey(คีย์การวัด) ·ruleId·polarity·source(ประโยคกฎ KB ที่เป็นพื้นฐานของคำอ่าน) มาด้วย ID กฎที่เป็นหลักฐานรวมอยู่ในmeta.kbRuleIds meta.disclaimerเป็นentertainment_referenceเสมอ โปรดแสดงmeta.disclaimerText(หรือข้อความที่มีความหมายเดียวกัน) บนหน้าจอผู้ใช้ด้วย
รหัสข้อผิดพลาด
| HTTP | code | ความหมาย |
|---|---|---|
| 400 | READING_INPUT_ONE_OF | โหงวเฮ้ง: ไม่ได้ส่ง image หรือ landmarks อย่างใดอย่างหนึ่งพอดี |
| 400 | IMAGE_REQUIRED | ลายมือ: ไม่มี image |
| 400 | CONSENT_REQUIRED | เป็นรูปถ่ายแต่ไม่มี consent หรือค่าไม่ถูกต้อง |
| 400 | IMAGE_INVALID · IMAGE_FORMAT_UNSUPPORTED | อ่านรูปไม่ได้ · mimeType ต่างจากรูปแบบจริง · ไม่ใช่ JPEG · PNG · WebP (รวม WebP แบบเคลื่อนไหว) |
| 413 | IMAGE_TOO_LARGE | รูปเกิน 8MB · เกิน 8192px หรือ 16.8 เมกะพิกเซล · ด้านยาวของ WebP เกิน 1600px |
| 400 | IMAGE_NOT_ALLOWED | ดูเหมือนผู้เยาว์ · หลายใบหน้า / สองมือขึ้นไป · ไม่ใช่รูปใบหน้า · ฝ่ามือ |
| 400 | FACE_NOT_DETECTED · PALM_NOT_DETECTED | หาใบหน้า / ฝ่ามือไม่พบ (รูปหลังมือคือ PALM_NOT_DETECTED) |
| 400 | USE_FACE_MEASURE | llm: false กับ landmarks ของโหงวเฮ้ง — การวัดโดยไม่ใช้ AI คือ API วัดโหงวเฮ้ง |
| 400 | MEASURE_LOW_QUALITY | เบลอ · มืด · ถูกบัง · เล็กเกินไป · เอียง — เหตุผลอยู่ใน quality ของการตอบกลับ แนะนำให้ถ่ายใหม่ |
| 400 | CREASE_INVALID | จุดของเส้นลายมือน้อยกว่า 2 จุดหรืออยู่นอก 0~1 |
| 400 | MEASURE_* | อินพุต landmarks ผิดพลาด (รหัสเดียวกับการวัดโหงวเฮ้ง) |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ — ตรวจก่อนเรียกโมเดลภายนอก |
| 404 | face_reading_not_enabled · palm_reading_not_enabled | ฟีเจอร์ที่ยังไม่เปิด |
| 409 | IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS | ใช้ X-Idempotency-Key เดียวกันกับเนื้อหาอื่น · คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่ (ดูการลองใหม่และการส่งซ้ำด้านล่าง) |
| 429 | FILTERED_QUOTA_EXCEEDED | รูปที่ถูกกรองวันนี้ถึงเพดานรายวันแล้ว — ดูเพดานรายวันของรูปที่ถูกกรองด้านล่าง |
| 502 | READING_UNAVAILABLE | สร้างคำอ่านไม่ได้ (รวมกรณีเอาต์พุตถูกตัด) — โปรดลองใหม่อีกครั้ง |
| 503 | IMAGE_BUSY | การประมวลผลรูปถ่ายหนาแน่น — โปรดลองใหม่ในภายหลัง |
| 504 | LLM_UPSTREAM_TIMEOUT | โมเดลภายนอกตอบกลับเกินเวลา |
การคิดค่าบริการ
- ราคาอยู่ในตารางราคา คิดค่าบริการเฉพาะการตอบกลับ 200 ข้อผิดพลาด 4xx · 5xx และความล้มเหลวทั้งหมดเป็น ₩0 (รวมรูปที่ถูกกรองและ 502 จากเอาต์พุตที่ถูกตัด) การเรียก
landmarksที่ไม่มีคีย์การวัดหรือบันทึก KB ที่ตรงเลยก็เป็น ₩0 - endpoint ในบันทึกการใช้งานคือ
face-reading/palm-reading - API รูปถ่ายเรียกได้ด้วยคีย์เซิร์ฟเวอร์เท่านั้น (คีย์ "เชื่อมต่อ AI" สำหรับแอปเท่านั้นจะได้ 403
APP_KEY_SCOPE) โปรดส่งรูปผ่านเซิร์ฟเวอร์ของพาร์ทเนอร์
เพดานรายวันของรูปที่ถูกกรอง
รูปที่ถูกกรองหลังผ่านการจำแนก (IMAGE_NOT_ALLOWED · FACE_NOT_DETECTED · PALM_NOT_DETECTED · MEASURE_LOW_QUALITY) และ 502 ที่เกิดจากเอาต์พุตถูกตัด เป็น ₩0 สำหรับพาร์ทเนอร์ แต่มีค่าใช้จ่ายโมเดลภายนอก จึงรับได้ต่อพาร์ทเนอร์ต่อวันตามเวลาเกาหลี (00:00~24:00) ไม่เกินค่าที่มากกว่าระหว่าง 200 รายการ กับ 3 เท่าของจำนวนการอ่านรูปที่สำเร็จในวันนั้น หากเกินจะตอบ 429 FILTERED_QUOTA_EXCEEDED (₩0 เนื้อหามี filtered · limit) ก่อนเรียกโมเดลภายนอก และจะปลดล็อกเวลา 00:00 (KST) ของวันถัดไป หากแสดงคำแนะนำการถ่าย (หน้าตรง · สว่าง · คนเดียว · ฝ่ามือ) ให้ผู้ใช้ก่อน รูปที่ถูกกรองจะลดลง การเรียก landmarks ไม่ถูกนับ
การลองใหม่และการส่งซ้ำ (X-Idempotency-Key)
เมื่อส่งใหม่เพราะเครือข่ายขาด โปรดแนบเฮดเดอร์ X-Idempotency-Key (1~128 ตัวอักษร ASCII ที่พิมพ์ได้) หากพาร์ทเนอร์เดียวกันส่งคีย์เดียวกันและเนื้อหาเดียวกัน (รวมรูปถ่าย) ซ้ำภายใน 24 ชั่วโมง จะคืนผลที่ได้ครั้งแรกตามเดิม — ไม่คิดค่าบริการใหม่และไม่เรียกโมเดลภายนอก และจะมีเฮดเดอร์การตอบกลับ Idempotent-Replayed: true แนบมา
- คีย์เดียวกันกับเนื้อหาอื่น: 409
IDEMPOTENCY_KEY_REUSED(₩0) — คำขอใหม่ให้ใช้คีย์ใหม่ - คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่: 409
IDEMPOTENCY_IN_PROGRESS(₩0) — รอสักครู่แล้วส่งใหม่ด้วยคีย์เดิม - เก็บเฉพาะผล 200 ที่คิดค่าบริการแล้ว หากเป็นการตอบกลับข้อผิดพลาด · ₩0 เมื่อส่งซ้ำด้วยคีย์เดิมจะประมวลผลใหม่
- สิ่งที่เก็บมีเพียงแฮชของคีย์ แฮชของเนื้อหา และผลที่เข้ารหัสแล้ว และจะลบหลัง 24 ชั่วโมง ไม่เก็บรูปถ่าย
- หากไม่มีเฮดเดอร์ จะประมวลผลและคิดค่าบริการทุกคำขอเหมือนเดิม
API ศาสตร์ชื่อ
คืนการอ่านศาสตร์ชื่อจากชื่อ (ฮันกึล และฮันจาหากทราบ) และวันเดือนปีเกิดหากต้องการ การตอบกลับแบ่งเป็น deterministic ที่โค้ดคำนวณ (ธาตุตามเสียง · จำนวนขีด · 4 ส่วนของเลข 81 · ธาตุตามความหมายอักษร · การเสริมธาตุช่วย) และ interpretation ที่ AI เขียนโดยอิงเฉพาะค่าเหล่านั้น การคำนวณแต่ละรายการจะมี ID กฎ KB ศาสตร์ชื่อที่เป็นหลักฐานแนบมา ผลลัพธ์คือการอ่านศาสตร์ชื่อแบบดั้งเดิมเพื่อความบันเทิงและการอ้างอิง
- อ่านความหมายชื่อ (ค่าเริ่มต้น): คำนวณ + การตีความโดย AI ชื่อจะถูกส่งไปยัง OpenAI (สหรัฐอเมริกา) จึงต้องมี
consent - คำนวณชื่อ (
"interpret": false): คำนวณอย่างเดียว ไม่เรียก AIinterpretationเป็นnullและไม่ต้องมีconsentทั้งสองแบบราคาต่างกัน (ตารางราคา) - ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี แม้ส่ง
langอื่นก็ตอบเป็นภาษาเกาหลี (langในการตอบกลับ ="ko")
POST /api/v1/partners/v1/naming
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
name.hangul | string | ✓ | ชื่อฮันกึล 2~6 พยางค์ เริ่มจากนามสกุล (เช่น 김하늘) 남궁 (Namgung) · 황보 (Hwangbo) · 제갈 (Jegal) · 선우 (Seonu) · 독고 (Dokgo) · 사공 (Sagong) · 서문 (Seomun) · 동방 (Dongbang) ถือเป็นนามสกุลสองพยางค์ |
name.hanja | (string|null)[] | ฮันจาหนึ่งตัวต่อพยางค์ หากไม่ทราบเป็น null หากความยาวต่างจากจำนวนพยางค์จะได้ 400 NAME_HANJA_LENGTH | |
name.strokes | (number|null)[] | จำนวนขีดแบบดั้งเดิม (ตามอักษรต้นแบบ) ต่อพยางค์ (1~64) หากไม่ทราบเป็น null (ดูคำอธิบายจำนวนขีดด้านล่าง) | |
name.meanings | (string|null)[] | ความหมายของฮันจาต่อพยางค์ (훈 เช่น 물 · 쇠 1~20 ตัวอักษร) ธาตุตามความหมายอักษรจะดูจากความหมายนี้เท่านั้น | |
birth | object | { year, month, day, hour?, minute?, gender?, timezone? } (สุริยคติ) หากส่งมาจะคำนวณธาตุช่วยของซาจูแล้วดูว่าชื่อเติมธาตุนั้นหรือไม่ timezone ค่าเริ่มต้น Asia/Seoul วันเดือนปีเกิดจะไม่ถูกส่งไปยังโมเดลภายนอก | |
interpret | boolean | ค่าเริ่มต้น true (อ่านความหมายชื่อ) หากเป็น false จะคำนวณชื่ออย่างเดียว (ไม่ใช้ AI) | |
echoName | boolean | เพิ่มเมื่อ 2026-10-31 ค่าเริ่มต้น true (เหมือนตอนนี้) หากเป็น false จะไม่เขียนตัวอักษรของชื่อซ้ำที่ใดในการตอบกลับเลย — name เป็น null และ hangul · hanja · meaning ของ deterministic.syllables เป็น null แต่จะมี position (เริ่มจาก 1) แนบมาแทน การแสดงตัวอักษรใน items ก็เปลี่ยนเป็นตำแหน่ง เช่น "첫 글자(목(木))" ("อักษรตัวแรก (ธาตุไม้)") และหากเป็นการอ่านความหมายชื่อ จะไม่ส่งตัวชื่อไปยัง AI (ส่งเฉพาะค่าที่คำนวณและตำแหน่ง) | |
consent | object | ✓ หากอ่านความหมายชื่อ | { "version": "name-consent-2026-10", "subject": "end_user" } — version คือเวอร์ชันของข้อความขอความยินยอมที่พาร์ทเนอร์แสดง (1~40 ตัวอักษร) subject คือ end_user · third_party หากไม่มีหรือค่าไม่ถูกต้องจะได้ 400 CONSENT_REQUIRED บันทึกการใช้งานเก็บเพียง version และ subject หาก interpret: false ไม่ต้องใช้ |
lang | string | รับ ko · en · ja · th แต่ตอนนี้ตอบเป็นภาษาเกาหลีเท่านั้น | |
endUserId | string | ID ผู้ใช้ปลายทางของพาร์ทเนอร์ (เฉพาะในบันทึกการใช้งาน) |
- จำนวนขีดคำนวณเป็นจำนวนขีดแบบดั้งเดิม (ตามอักษรต้นแบบ) (เช่น 氵 นับเป็น 水 4 ขีด) ฮันจาที่เซิร์ฟเวอร์รู้จำนวนขีดมีเพียงอักษรนามสกุล 38 ตัว (
R-NAME-STROKE-004) และ 11 ตัวที่ค่าต่างกันตามพจนานุกรม (洪·沈·河·池·鄭·郭·陳·權·禹·羅·尹) จะเว้นว่างไว้ด้วยstrokeNote: "disputed"ฮันจาอื่นต้องส่งจำนวนขีดแบบดั้งเดิม (ตามอักษรต้นแบบ) ทางname.strokesจึงจะได้ 4 ส่วน หากมีพยางค์ใดไม่มีจำนวนขีดแม้แต่พยางค์เดียว จะได้suri: null,suriMissing: "strokes_unknown" - ธาตุตามเสียงกำหนดจากพยัญชนะต้น และใช้การจัดเสียงคอ (ㅇ·ㅎ) = ดิน · เสียงริมฝีปาก (ㅁ·ㅂ·ㅍ) = น้ำ (
R-NAME-SOUND-011)
ตัวอย่างคำขอ
{
"name": { "hangul": "김민수", "hanja": ["金", "民", "秀"], "strokes": [null, 5, 7], "meanings": ["쇠", null, null] },
"birth": { "year": 1990, "month": 5, "day": 17, "hour": 9 },
"consent": { "version": "name-consent-2026-10", "subject": "end_user" }
}
หากต้องการเฉพาะการคำนวณชื่อ ให้ใส่ "interpret": false และไม่ต้องใส่ consent ในกรณีนั้น interpretation ในการตอบกลับเป็น null และรายการโมเดลภายนอกของ meta.processing เป็น null
ตัวอย่างการตอบกลับ (ย่อ)
{
"success": true,
"data": {
"name": { "hangul": "김민수", "hanja": ["金", "民", "秀"] },
"deterministic": {
"surnameLength": 1,
"syllables": [
{ "index": 0, "hangul": "김", "hanja": "金", "strokes": 8, "strokeSource": "kb", "strokeNote": null, "strokeRuleId": "R-NAME-STROKE-004", "soundElement": "wood", "soundRuleId": "R-NAME-SOUND-004", "meaning": "쇠", "rootElement": "metal" },
{ "index": 1, "hangul": "민", "hanja": "民", "strokes": 5, "strokeSource": "input", "strokeNote": null, "strokeRuleId": null, "soundElement": "water", "soundRuleId": "R-NAME-SOUND-010", "meaning": null, "rootElement": null },
{ "index": 2, "hangul": "수", "hanja": "秀", "strokes": 7, "strokeSource": "input", "strokeNote": null, "strokeRuleId": null, "soundElement": "metal", "soundRuleId": "R-NAME-SOUND-006", "meaning": null, "rootElement": null }
],
"soundFlow": { "elements": ["wood", "water", "metal"], "relations": ["reverse_generating", "reverse_generating"], "generating": 0, "overcoming": 0, "score": 0.5 },
"suri": {
"won": { "sum": 12, "number": 12, "grade": "bad" },
"hyung": { "sum": 13, "number": 13, "grade": "good" },
"i": { "sum": 15, "number": 15, "grade": "good" },
"jeong": { "sum": 20, "number": 20, "grade": "bad" }
},
"suriMissing": null,
"yongshin": { "element": "wood", "supplied": true, "suppliedBy": ["sound"] },
"kbRuleIds": ["R-NAME-JAWON-001", "R-NAME-MODERN-001", "R-NAME-MODERN-003", "R-NAME-SOUND-004", "R-NAME-SOUND-006", "R-NAME-SOUND-010", "R-NAME-SOUND-011", "R-NAME-STROKE-004"]
},
"interpretation": { "text": "첫 글자는 목, 가운데 글자는 수, 끝 글자는 금 기운이에요. 소리가 서로 부딪치지 않고 이어지는 이름으로 읽혀요." },
"items": [
{ "key": "sound_flow", "label": "발음오행 흐름", "score": 0.5, "reason": "김(목(木)) → 민(수(水)) → 수(금(金)) · 상생 0 · 상극 0", "ruleId": "R-NAME-SOUND-011" },
{ "key": "suri_hyung", "label": "형격", "grade": "good", "score": 13, "reason": "획수 합 13 → 13수(길)", "ruleId": "R-NAME-MODERN-001" },
{ "key": "yongshin_match", "label": "용신 보완", "grade": "supplied", "reason": "용신 목(木)을 이름이 발음으로 채워 줘요" }
],
"summary": "부드럽게 이어지는 소리에 용신 기운이 담긴 이름으로 읽혀요.",
"lang": "ko",
"meta": {
"input": "name",
"processing": { "provider": "OpenAI", "model": "gpt-5.6-luna", "region": "US", "store": false, "retention": "API 입력은 학습에 쓰지 않음, 오남용 감시로 최대 30일 보관 뒤 삭제", "imageStored": false },
"disclaimer": "entertainment_reference",
"disclaimerText": "전통 관상·손금·성명학을 재미와 참고로 풀어 본 내용이에요. 사실 판단이나 진단이 아니에요.",
"kbRuleIds": ["R-NAME-JAWON-001", "R-NAME-MODERN-001", "R-NAME-MODERN-003", "R-NAME-SOUND-004", "R-NAME-SOUND-006", "R-NAME-SOUND-010", "R-NAME-SOUND-011", "R-NAME-STROKE-004"]
}
}
}
- ค่าธาตุ:
wood·fire·earth·metal·waterความสัมพันธ์:generating(ส่งเสริม) ·overcoming(ข่ม) ·same(ธาตุเดียวกัน) ·reverse_generating(ตัวหลังส่งเสริมตัวหน้า) gradeของเลข 81:good(ดี) ·mixed(ดีครึ่งร้ายครึ่ง) ·bad(ร้าย) ตารางดีร้ายของเลข 81 เป็นแนวปฏิบัติสมัยใหม่ที่ไม่มีต้นฉบับคลาสสิก (R-NAME-MODERN-001)itemsคือการย้ายdeterministicมาอยู่ในรูปแบบเดียวกับหน้าจออื่น (key·label·grade·score·reason·ruleId) 4 ส่วนจะรวมเฉพาะเมื่อมีจำนวนขีดครบ- ประโยคการอ่านจะไม่ยกตัวอักษรของชื่อในเครื่องหมายคำพูด หรือชี้ทีละตัว (เพิ่มเมื่อ 2026-10-31) จะพูดถึงตัวอักษรเฉพาะในรูปตำแหน่ง เช่น "อักษรตัวแรก · อักษรตัวกลาง · อักษรตัวสุดท้าย" เซิร์ฟเวอร์ตรวจผลลัพธ์ หากมีประโยคที่ครอบตัวอักษรของชื่อด้วยเครื่องหมายคำพูดหรือเขียนชื่อเต็ม จะเขียนใหม่เพียงครั้งเดียวด้วยคำสั่งที่เข้มงวดขึ้น (ไม่มีค่าบริการเพิ่ม) หากยังเหลืออยู่ จะเปลี่ยนส่วนนั้นเป็นคำบอกตำแหน่ง ("‘김’과" → "첫 글자와" คือ "กับ ‘คิม’" → "กับอักษรตัวแรก") และ "이 이름" ("ชื่อนี้") แล้วคืนให้ ตัวอักษรเดี่ยวที่เขียนโดยไม่มีเครื่องหมายคำพูด (เช่น ตัวอักษรที่พบบ่อยอย่างคำช่วย) แยกจากคำทั่วไปไม่ได้ จึงไม่เปลี่ยน
- ตัวอย่างการตอบกลับ
"echoName": false(เพิ่มเมื่อ 2026-10-31 ย่อ) — ใช้เมื่อต้องการแสดงเฉพาะผลโดยไม่มีชื่อ"name": null, "deterministic": { "syllables": [ { "index": 0, "position": 1, "hangul": null, "hanja": null, "strokes": 8, "strokeSource": "kb", "soundElement": "wood", "meaning": null, "rootElement": "metal", ... }, { "index": 1, "position": 2, "hangul": null, "hanja": null, "strokes": 5, "soundElement": "water", "meaning": null, ... }, { "index": 2, "position": 3, "hangul": null, "hanja": null, "strokes": 7, "soundElement": "metal", "meaning": null, ... } ], ... }, "items": [ { "key": "sound_flow", "label": "발음오행 흐름", "score": 0.5, "reason": "첫 글자(목(木)) → 가운데 글자(수(水)) → 끝 글자(금(金)) · 상생 0 · 상극 0", "ruleId": "R-NAME-SOUND-011" }, ... ]
รหัสข้อผิดพลาด
| HTTP | code | ความหมาย |
|---|---|---|
| 400 | NAME_INVALID | ชื่อฮันกึลไม่ใช่ 2~6 พยางค์ · รูปแบบค่า hanja/strokes/meanings ผิดพลาด |
| 400 | NAME_HANJA_LENGTH | ความยาวของ hanja ต่างจากจำนวนพยางค์ |
| 400 | CONSENT_REQUIRED | อ่านความหมายชื่อแต่ไม่มี consent หรือค่าไม่ถูกต้อง |
| 400 | (ข้อผิดพลาดการตรวจสอบ) | วันที่ไม่มีอยู่จริง · ฟิลด์ที่ไม่มีในเอกสาร |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
| 404 | naming_not_enabled | ฟีเจอร์ที่ยังไม่เปิด (อ่านความหมายชื่อ · คำนวณชื่อ แยกกัน) |
| 409 | IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS | ใช้ X-Idempotency-Key เดียวกันกับเนื้อหาอื่น · คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่ (ดูการลองใหม่และการส่งซ้ำด้านล่าง) |
| 502 | READING_UNAVAILABLE | สร้างการตีความโดย AI ไม่ได้ — ไม่คิดค่าบริการ (ไม่มีการคิดค่าบริการบางส่วนที่คืนเฉพาะการคำนวณ) โปรดลองใหม่อีกครั้ง |
| 504 | LLM_UPSTREAM_TIMEOUT | โมเดลภายนอกตอบกลับเกินเวลา |
การคิดค่าบริการ
- ราคาอยู่ในตารางราคา (คำนวณชื่อ · อ่านความหมายชื่อ) คิดค่าบริการเฉพาะการตอบกลับ 200 ข้อผิดพลาด 4xx · 5xx และความล้มเหลวทั้งหมดเป็น ₩0 endpoint ในบันทึกการใช้งานของทั้งสองคือ
namingเรียกได้ด้วยคีย์ "เชื่อมต่อ AI" สำหรับแอปเท่านั้นด้วย
การลองใหม่และการส่งซ้ำ (X-Idempotency-Key)
เมื่อส่งใหม่ โปรดแนบเฮดเดอร์ X-Idempotency-Key (1~128 ตัวอักษร ASCII ที่พิมพ์ได้) หากพาร์ทเนอร์เดียวกันส่งคีย์เดียวกันและเนื้อหาเดียวกันซ้ำภายใน 24 ชั่วโมง จะคืนผลที่ได้ครั้งแรกตามเดิม — ไม่คิดค่าบริการใหม่และไม่เรียก AI และจะมีเฮดเดอร์การตอบกลับ Idempotent-Replayed: true แนบมา
- คีย์เดียวกันกับเนื้อหาอื่น: 409
IDEMPOTENCY_KEY_REUSED(₩0) — คำขอใหม่ให้ใช้คีย์ใหม่ - คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่: 409
IDEMPOTENCY_IN_PROGRESS(₩0) — รอสักครู่แล้วส่งใหม่ด้วยคีย์เดิม - เฉพาะผล 200 ที่คิดค่าบริการแล้วจะถูกเข้ารหัสและเก็บไว้ 24 ชั่วโมงพร้อมแฮชของคีย์ · แฮชของเนื้อหา หากเป็นการตอบกลับข้อผิดพลาด · ₩0 เมื่อส่งซ้ำด้วยคีย์เดิมจะประมวลผลใหม่ หากไม่มีเฮดเดอร์ จะประมวลผลและคิดค่าบริการทุกคำขอเหมือนเดิม
meta.disclaimerคือentertainment_referenceโปรดแสดงmeta.disclaimerTextบนหน้าจอผู้ใช้ด้วย
API ไพ่ทาโรต์
POST /api/v1/partners/v1/tarot
เมื่อกำหนดจำนวนใบ (count 1~10 ใบ) หรือรูปแบบการวางไพ่ (spread) จะสุ่มไพ่จากสำรับ 78 ใบ (เมเจอร์ 22 · ไมเนอร์ 56) โดยไม่ซ้ำกัน แล้วคืนหัวตั้ง · หัวกลับ คีย์เวิร์ด ความหมาย ที่อยู่รูปไพ่ของแต่ละใบ ไม่มีการตีความโดย AI — ความหมายคือประโยคที่กำหนดไว้ของไพ่ตามเดิม จึงมีวิธีใช้สามแบบ
- เรียกไพ่ทาโรต์อย่างเดียวเพื่อสร้างแอป — นำชื่อไพ่ · ความหมาย · รูปในการตอบกลับไปแสดงบนหน้าจอตามเดิม
- ไพ่ทาโรต์ + LLM เพื่อตีความ — ส่งไพ่ที่สุ่มได้เป็นอินพุตของ LLM API แล้วเขียนคำอ่านเอง
- ใช้ร่วมกับ AI ซาจู — หากใส่
tarotในคำขอ AI อ่านดวงซาจู จะอ่านไพ่ทาโรต์ไปพร้อมกับการอ่านซาจู (รายการที่รวมอยู่)
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
count | number | △ | จำนวนใบที่จะสุ่ม 1~10 (จำนวนเต็ม) ส่ง count หรือ spread อย่างใดอย่างหนึ่งเท่านั้น หากส่งทั้งสองหรือไม่ส่งเลยจะได้ 400 |
spread | string | △ | รูปแบบการวางไพ่ กำหนดจำนวนใบและชื่อตำแหน่งไว้แล้ว: single (ไพ่ประจำวัน 1 ใบ) · past-present-future (อดีต · ปัจจุบัน · อนาคต 3 ใบ) · choice (ทางเลือก: สถานการณ์ปัจจุบัน · อุปสรรค · ผลลัพธ์ 3 ใบ) · celtic-condensed (เซลติกแบบย่อ 5 ใบ) · future-prediction (ทำนายอนาคต 5 ใบ) |
reversed | boolean | อนุญาตไพ่หัวกลับ (ค่าเริ่มต้น true) หากเป็น false จะเป็นหัวตั้งทั้งหมด | |
seed | string | สตริงสำหรับทำซ้ำ (1~200 ตัวอักษร) seed เดียวกัน + count/spread เดียวกัน + reversed เดียวกัน จะได้ไพ่เดิมเสมอ หากไม่มีจะสุ่มทุกครั้ง (ตัวเลขสุ่มเชิงวิทยาการเข้ารหัส) | |
question | string | คำถามของผู้ใช้ปลายทาง (สูงสุด 500 ตัวอักษร) ไม่ใช้ในการตีความ แต่คืนในการตอบกลับตามเดิม — เป็นฟิลด์ที่มีไว้เพื่อความสะดวกเมื่อส่งต่อไปยังขั้น LLM ถัดไป | |
lang | string | ภาษาของชื่อไพ่ · คีย์เวิร์ด · ความหมาย · ชื่อรูปแบบการวางไพ่: ko (ค่าเริ่มต้น) · en · ja · th |
ตัวอย่างคำขอ
{
"spread": "past-present-future",
"question": "올해 하반기에 이직해도 될까요?",
"seed": "user-1042:2026-10-10"
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/tarot \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"count": 1, "lang": "en", "reversed": false}'
ตัวอย่างการตอบกลับ (ตัดตอนไพ่ 1 ใบ)
{
"success": true,
"data": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": "hrum-example-1",
"cards": [
{
"position": 1,
"positionLabel": "과거",
"id": "wands_10",
"name": "완드의 10",
"nameEn": "Ten of Wands",
"arcana": "wands",
"reversed": true,
"keywords": ["내려놓기", "위임", "해방"],
"meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.",
"imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp"
}
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp",
"question": "올해 하반기에 이직해도 될까요?",
"costPoints": 20
}
}
cards[]:position(เริ่มจาก 1 ลำดับที่สุ่ม = ตำแหน่งในรูปแบบการวาง) ·positionLabel(ชื่อตำแหน่งในรูปแบบการวาง หากสุ่มด้วยcountเป็นnull) ·id(ค่าเฉพาะของไพ่ที่ไม่ขึ้นกับภาษา) ·name(ภาษาที่ขอ) ·nameEn·arcana(major|wands|cups|swords|pentacles) ·reversed·keywords·meaning(ของทิศทางที่สุ่มได้) ·imageUrlspread: หากสุ่มด้วยcountจะเป็นnull- รูปไพ่:
imageUrl·cardBackUrlเป็น WebP (กว้าง 600px) และที่อยู่มีเวอร์ชัน (v2) จึงไม่เปลี่ยน — ดาวน์โหลดมาแคชไว้แล้วใช้ตามเดิมได้ ไพ่หัวกลับให้หมุนรูป 180 องศาเพื่อแสดง (ตัวรูปมีแบบหัวตั้งแบบเดียว) - แหล่งที่มาของภาพ: สแกนจากต้นฉบับ Rider-Waite ปี 1909 (Pamela Colman Smith สาธารณสมบัติ) ไพ่ทั้ง 78 ใบและด้านหลังเป็นสแกนต้นฉบับปี 1909 จาก Wikimedia Commons แหล่งที่มา · สัญญาอนุญาตของแต่ละไฟล์อยู่ในบัญชีแหล่งที่มา ที่อยู่เดิม (
v1) ก็ยังคืนรูปเดียวกัน จึงไม่ต้องเปลี่ยนที่อยู่ที่เก็บไว้แล้ว costPoints: ยอดที่หักในการเรียกครั้งนี้ (₩)
ราคา
- ค่าบริการคงที่ 1 ครั้งต่อการเรียก — สุ่ม 1 ใบหรือ 10 ใบก็เท่ากัน ราคาอยู่ในตารางแบบคำนวณของราคา คิดค่าบริการเฉพาะการเรียกที่สำเร็จ และการเรียกซ้ำด้วยอินพุตเดิมก็คิดค่าบริการแยกกัน (Idempotency)
- อินพุตผิดพลาด (400) · ยอดคงเหลือไม่พอ (402) ไม่คิดค่าบริการ endpoint ในบันทึกการใช้งานคือ
tarot - หากเรียกขณะที่ยังไม่เปิด จะได้ 404
tarot_not_enabled(ไม่คิดค่าบริการ)
หลักฐานจากต้นฉบับ Waite kb
เมื่อเปิดแล้ว การตอบกลับจะมี kb แนบมา สำหรับไพ่แต่ละใบที่สุ่มได้ จะคืนความหมายหัวตั้ง · หัวกลับของไพ่ใบนั้นจากต้นฉบับ A. E. Waite, The Pictorial Key to the Tarot (1910 สาธารณสมบัติ) พร้อม ID กฎ (R-TAROT-*) และการอ้างอิงต้นฉบับ meaning · keywords ข้างต้นคงเดิม เพิ่มเพียง kb และราคาเท่าเดิม
kb.cards[]:position·id·reversed·drawn(ความหมายของทิศทางที่สุ่มได้) ·upright·reversedMeaning·positionRuleแต่ละความหมายมีruleId·status·statement(ภาษาเกาหลี) ·quotes[](quoteต้นฉบับภาษาอังกฤษlocationบทและตอนfoundAtบรรทัดในต้นฉบับ) ·variants[](คำอธิบายอื่นที่ Waite เขียนไว้alternativeความหมายเพิ่มเติมจากภาค 3 §4additional)statusใช้ตามที่ KB ระบุ (verified= มีการอ้างอิงต้นฉบับ) ตำแหน่งที่ Waite ไม่ได้เขียนความหมายไว้ (ไพ่ถ้วย 2 หัวกลับ) จะเป็นruleId: null,status: "disputed"method: "celtic-cross": วิธีดูไพ่แบบเซลติกที่ Waite เขียนไว้ในหนังสือ (10 ใบ) ส่งแทนcount·spreadและความหมายตำแหน่งของ Waite สำหรับแต่ละตำแหน่งของ 10 ใบจะอยู่ในpositionRulespreadอื่นเป็นการจัดวางที่ไม่มีในต้นฉบับของ Waite จึงไม่มีหลักฐานของตำแหน่ง (kb.method: null)kb.caveats: คำของ Waite ที่ว่าความหมายเปลี่ยนตามตำแหน่ง และหลักการใช้งาน (เป็นเครื่องมือการดูดวง ไม่ได้แทนการตัดสินใจด้านสุขภาพ · กฎหมาย · การเงิน)- หากส่ง
methodก่อนเปิด จะได้ 404tarot_kb_not_enabled(ไม่คิดค่าบริการ)
{
"method": "celtic-cross",
"seed": "user-1042:2026-10-11"
}
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | tarot_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 404 | tarot_kb_not_enabled | ส่ง method แต่หลักฐานจากต้นฉบับยังไม่เปิด |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
ต้องส่ง count · spread · method อย่างใดอย่างหนึ่งพอดี หากส่งสองอย่างขึ้นไปหรือไม่ส่งเลยจะได้ 400 ทั่วไป
API ผังดวงกำเนิด (Natal Chart) (โหราศาสตร์ตะวันตก) เลิกจำหน่าย
/astrology) แทน ด้วยอินพุตการเกิดเดียวกัน จะได้ 10 ดาว · เรือน · มุมสัมพันธ์ ไปจนถึงย่อหน้าการอ่านที่เขียนไว้ล่วงหน้าในครั้งเดียว ₩50 ต่อครั้ง การเรียก /natal-chart ที่เชื่อมไว้แล้วยังทำงานตามเดิม แต่ไม่แนะนำสำหรับการเชื่อมต่อใหม่POST /api/v1/partners/v1/natal-chart
คำนวณผังดวงกำเนิดของโหราศาสตร์ตะวันตก (ตำแหน่งดาว 7 ดวง ดวงอาทิตย์ · ดวงจันทร์ · ดาวพุธ · ดาวศุกร์ · ดาวอังคาร · ดาวพฤหัสบดี · ดาวเสาร์ + ลัคนา) จากวันเดือนปีและเวลาเกิด ไม่รวมดาวยูเรนัส · เนปจูน · พลูโต ใช้จักรราศีแบบทรอปิคัลของโหราศาสตร์ตะวันตก ไม่ใช่จุดเปลี่ยนฤดู
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
birthDate |
string | O | วันเกิด YYYY-MM-DD (สุริยคติ) เฉพาะวันที่ที่มีจริงในปฏิทิน (ปฏิเสธวันอย่าง 30 กุมภาพันธ์) |
birthTime |
string | เวลาเกิด HH:mm (24 ชม.) หากละ birthTimePrecision จะถือเป็น exact และคำนวณด้วยเวลานี้ (ตั้งแต่ 2026-10-17) หากไม่ต้องการใช้เวลา ให้ตัด birthTime ออกหรือส่ง birthTimePrecision: "unknown" |
|
gender |
string | เพศ ("male" | "female") รับไว้เพื่อความเข้ากันได้เท่านั้น ไม่ใช้ในการคำนวณ | |
birthLatitude |
number | ละติจูด -90~90 (จำเป็นสำหรับการคำนวณลัคนา ใช้คู่กับลองจิจูด) | |
birthLongitude |
number | ลองจิจูด -180~180 | |
birthTimezoneOffset |
number | ค่าชดเชย UTC (นาที) ค่าเริ่มต้น: 540 (KST) | |
birthTimePrecision |
string | "exact" | "approximate" (ระดับชั่วโมง) | "unknown" หากละไว้ ถ้ามี birthTime เป็น exact ถ้าไม่มีเป็น unknown (คำนวณตามเที่ยงวัน) |
|
readings |
boolean | หากเป็น true การตอบกลับจะแนบ readings (ย่อหน้าการอ่านศักดิ์ของดาว · มุมสัมพันธ์) เพิ่ม ₩20 หากบัญชียังไม่เปิดจะได้ 404 natal_readings_not_enabled (ไม่คิดค่าบริการ) |
|
lang |
string | ภาษาของย่อหน้า readings — ko (ค่าเริ่มต้น) · en · ja · th |
ฟิลด์ในการตอบกลับ
| ฟิลด์ | ชนิด | คำอธิบาย |
|---|---|---|
sun |
object | ตำแหน่งดวงอาทิตย์ { body, sign (ภาษาเกาหลี), signEn, element (ภาษาเกาหลี: 불·흙·공기·물 = ไฟ · ดิน · ลม · น้ำ), degreeInSign, eclipticLongitude } |
moon |
object | ตำแหน่งดวงจันทร์ |
mercury |
object | ตำแหน่งดาวพุธ |
venus |
object | ตำแหน่งดาวศุกร์ |
mars |
object | ตำแหน่งดาวอังคาร |
jupiter |
object | ตำแหน่งดาวพฤหัสบดี |
saturn |
object | ตำแหน่งดาวเสาร์ |
ascendant |
object|null | ลัคนา คำนวณเมื่อมีเวลาเกิดและพิกัด และ birthTimePrecision เป็น exact (รวมกรณีละไว้) หรือ approximate นอกนั้นเป็น null |
ascendantReason |
string | เหตุผลที่ลัคนาเป็น null (เฉพาะเมื่อมี เช่น ความแม่นยำของเวลาเป็น unknown หรือไม่มีพิกัด) |
ascendantHourBasis |
boolean | หากเป็นลัคนาที่คำนวณจากเวลา approximate (ระดับชั่วโมง) จะเป็น true — ให้แสดงว่า "อิงระดับชั่วโมง" |
ascendantEstimate |
object|null | การประมาณลัคนาในช่วง ±60 นาทีเมื่อเป็น approximate window = { startLocal, endLocal, switchLocal, beforeSign, afterSign } (switchLocal คือเวลาที่ราศีเปลี่ยนในช่วงนั้น หากไม่เปลี่ยนเป็น null) |
moonSignUncertain |
boolean | รวมเฉพาะเมื่อไม่ทราบเวลา (unknown) — หากราศีจันทร์เปลี่ยนภายในวันนั้นจะเป็น true (ราศีจันทร์ตามเที่ยงวันไม่แน่นอน) |
coordsBasis |
string|null | ตำแหน่งที่ใช้คำนวณลัคนา: "coords" (พิกัดที่ส่งมา) หรือ null (ไม่มีพิกัด · ไม่ทราบเวลา) |
engineVersion |
string | ฉบับการคำนวณ ปัจจุบัน "natal-2" — เป็นเครื่องหมายว่าผลอาจต่างจากการตอบกลับเดิมที่ไม่มีฟิลด์นี้ (ดูการเปลี่ยนแปลง 2026-10-17 ด้านล่าง) |
readings |
object | เฉพาะเมื่อ readings: true dignities (คำอ่านของดาวที่อยู่ในเกษตร · อุจจ์ · ประ · นิจ) · aspects (มุมสัมพันธ์ที่แม่นยำที่สุดไม่เกิน 2 รายการ deviation = องศาที่เบี่ยงจากมุมตรง) · lang · costWon (ค่าบริการเพิ่ม) · missingSections (จำนวนย่อหน้าที่ถูกตัดเพราะยังไม่มีประโยคการอ่าน 0 คือมีครบ — แม้บางส่วนขาดไปค่าบริการเพิ่มก็เท่าเดิม) · version (เครื่องหมายฉบับพจนานุกรมการอ่าน ค่าเท่ากันคือประโยคเดียวกัน — ใช้เปรียบเทียบ) |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/natal-chart \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"birthDate": "1990-05-15",
"birthTime": "12:00",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"birthTimezoneOffset": 540,
"birthTimePrecision": "exact"
}'
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"sun": {
"body": "Sun",
"sign": "황소자리",
"signEn": "Taurus",
"element": "흙",
"degreeInSign": 24.03,
"eclipticLongitude": 54.0343
},
"moon": { "body": "Moon", "sign": "염소자리", "signEn": "Capricorn", "element": "흙", ... },
"mercury": { "body": "Mercury", "sign": "황소자리", "signEn": "Taurus", ... },
"venus": { "body": "Venus", "sign": "양자리", "signEn": "Aries", "element": "불", ... },
"mars": { ... },
"jupiter": { ... },
"saturn": { ... },
"ascendant": {
"body": "Ascendant",
"sign": "사자자리",
"signEn": "Leo",
"element": "불",
"degreeInSign": 23.13,
"eclipticLongitude": 143.1256
},
"coordsBasis": "coords",
"engineVersion": "natal-2"
}
}
คำขอของตัวอย่างข้างต้น: {"birthDate": "1990-05-15", "birthTime": "12:00", "birthLatitude": 37.5665, "birthLongitude": 126.978, "birthTimezoneOffset": 540, "birthTimePrecision": "exact"} (ตัดตอนผลลัพธ์จริงของเอนจิน)
ย่อหน้าการอ่าน (readings: true)
แนบย่อหน้าการอ่านที่เขียนไว้ล่วงหน้าสำหรับศักดิ์ของดาว (เกษตร · อุจจ์ · ประ · นิจ) และมุมสัมพันธ์ที่แม่นยำที่สุด 2 รายการ เป็นย่อหน้าเดียวกับหน้าจอปฏิทินหมื่นปีของแอป INTA ด้านล่างคือผลลัพธ์จริงของเอนจิน (1990-09-04 14:30 พิกัดโซล exact)
{
"success": true,
"data": {
"sun": { ... }, "moon": { ... }, ...,
"readings": {
"dignities": [
{ "key": "Me_dom", "lang": "ko",
"text": "수성이 본궁인 쌍둥이자리나 처녀자리에 있으면 정보를 모으고 분류해 말로 옮기는 기능이 막힘없이 또렷하게 드러나요. 생각이 많아질 때 하나를 골라 끝까지 파고들면 그 명료함이 실제 성과로 이어져요." },
{ "key": "Sa_dom", "lang": "ko",
"text": "토성이 본궁인 염소자리나 물병자리에 있으면 책임을 지고 구조를 세워 반복 훈련으로 숙련을 쌓는 기능이 막힘없이 또렷하게 드러나요. 기준이 지나치게 굳어질 때 쉬어 갈 틈을 일정에 남겨 두면 그 인내가 성숙하게 쓰여요." }
],
"aspects": [
{ "key": "Me_Sa_tr", "deviation": 0.04, "lang": "ko",
"text": "수성과 토성의 트라인은 절제와 의지를 생각에 더해, 서두르지 않고 앞을 내다보며 구조를 짜는 데 힘이 실려요. 변화가 필요한 순간에 익숙한 방식만 고집할 수 있으니 새 방법도 한 번 시험해 보세요." },
{ "key": "Mo_Ma_sq", "deviation": 1.03, "lang": "ko",
"text": "달과 화성이 스퀘어를 이루면 감정이 올라오는 순간 욱하거나 규칙에 반발하는 쪽으로 기울 수 있어요. 화가 난 뒤 반응을 한 템포 늦추는 연습을 하면 그 뜨거움이 지켜야 할 것을 지키는 힘으로 바뀌어요." }
],
"lang": "ko",
"costWon": 20
}
}
}
- หากไม่ทราบเวลาเกิด (ไม่มี
birthTimeหรือbirthTimePrecision: "unknown") ตำแหน่งดวงจันทร์จะแกว่งมาก จึงถูกตัดออกจากการคำนวณมุมสัมพันธ์ - ย่อหน้าที่ไม่มีประโยคในภาษาที่ขอจะมาเป็นภาษาเกาหลี และ
langของย่อหน้านั้นจะเป็นko - หากดึงย่อหน้าการอ่านไม่ได้ จะได้ 503
natal_readings_unavailable(ไม่คิดค่าบริการ)
ข้อควรระวัง
- ราคา: ₩20 / ครั้ง (ตามการใช้งาน) · หาก
readings: trueเพิ่ม ₩20 (รวม ₩40) - การตรวจสอบวันที่: วันที่ไม่ถูกต้อง (เช่น 30 กุมภาพันธ์) หรือพิกัด/เขตเวลาที่ไม่ถูกต้องจะคืนข้อผิดพลาด 400 และไม่คิดค่าบริการ
- การคำนวณลัคนา: ต้องมีเวลาเกิด +
birthTimePrecision(exact/approximateหากละไว้เป็นexact) + ละติจูด/ลองจิจูดครบทั้งหมด หากขาดอย่างใดอย่างหนึ่งascendantจะเป็นnull - ข้อผิดพลาดของย่อหน้าการอ่าน: หาก
readings: trueแต่บัญชียังไม่เปิดจะได้ 404natal_readings_not_enabledหากดึงย่อหน้าไม่ได้จะได้ 503natal_readings_unavailable— ทั้งสองไม่คิดค่าบริการ - ดวงอาทิตย์/ดวงจันทร์/ลัคนา: ดาวแต่ละดวงและมุมต่างๆ อิงจักรราศีแบบทรอปิคัล (มาตรฐานโหราศาสตร์ตะวันตก)
- เปลี่ยนแปลง 2026-10-17 (
engineVersionnatal-2): หากส่งbirthTimeและละbirthTimePrecisionตอนนี้จะคำนวณด้วยเวลานั้น (เดิมละเว้นเวลาและคำนวณตามเที่ยงวัน ลัคนาจึงเป็นnull) เป็นกฎเดียวกับเอนด์พอยต์อื่น การเรียกที่ไม่มีbirthTimeหรือส่งความแม่นยำมาเองจะได้ผลเหมือนเดิม
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | natal_readings_not_enabled | readings: true แต่ยังไม่เปิดย่อหน้าการอ่าน |
| 503 | natal_readings_unavailable | ดึงย่อหน้าการอ่านไม่ได้ |
| 402 | (ไม่มี) | ยอดคงเหลือน้อยกว่าค่าเรียก — API นี้ไม่ตรวจยอดคงเหลือก่อนเรียก จึงได้ 402 ที่ไม่มีรหัส |
API โหราศาสตร์ตะวันตกแบบครบชุด
คืนการคำนวณโหราศาสตร์ตะวันตกทั้งหมดในการเรียกครั้งเดียวเหมือนปฏิทินหมื่นปี ค่าเริ่มต้นคือผังดวงกำเนิดเต็ม (10 ดาว ดวงอาทิตย์~พลูโต · จุดโหนดของดวงจันทร์ · 4 มุมหลัก · เรือน (ค่าเริ่มต้น Placidus) · มุมสัมพันธ์ · ศักดิ์ของดาว) และหากแนบบล็อกในคำขอ ทรานซิต + การเคลื่อนแบบ Secondary Progression (timing) และ ซินแนสทรีของสองคน (partner) จะมาในการตอบกลับเดียวกัน เลือกใช้เฉพาะส่วนที่ต้องการได้ ไม่ใช้ LLM นอกจากตัวเลขและคีย์กฎ (features) แล้ว ย่อหน้าการอ่าน (readings) ที่ HRUM เขียนไว้ล่วงหน้าจะมาด้วยเสมอโดยไม่มีค่าบริการเพิ่ม เป็นเอนจินโหราศาสตร์ตะวันตกตัวเดียวกับที่ INTA ใช้ ตำแหน่งดาวได้รับการตรวจสอบเทียบกับค่าอ้างอิงของ NASA/JPL Horizons · Swiss Ephemeris แล้ว (ดาวเคราะห์คลาดเคลื่อนไม่เกิน 0.005°) พารามิเตอร์การตีความ (ออร์บ · ชนิดมุม · ตารางศักดิ์) ทั้งหมดมาจากกฎในตำราคลาสสิก และค่าที่ตำราแต่ละเล่มเห็นต่างกัน (ออร์บของทรานซิต · โปรเกรสชัน) จะไม่มีค่าเริ่มต้นแต่ให้เลือกเอง (ดู "ค่าเริ่มต้นและค่าที่ต้องเลือกเอง" ด้านล่าง)
POST /api/v1/partners/v1/astrology
อินพุตการเกิดเหมือนกับ API ผังดวงกำเนิด (birthDate · birthTime · birthTimePrecision · birthLatitude · birthLongitude · birthTimezoneOffset ค่าเริ่มต้น 540 = KST นำเวลาออมแสงของเกาหลีและ UTC+8:30 ช่วงปี 1954~61 มาใช้อัตโนมัติ) หากละ birthTimePrecision จะเป็น unknown (อิงเที่ยงวัน)
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
houseSystems | string[] | เลือกจาก placidus · whole_sign · equal · porphyry หากละไว้เป็น ["placidus"] สถานที่เกิดในเขตขั้วโลก (ละติจูดประมาณ 66.56° ขึ้นไป angles.polar) จะคำนวณแบบ Porphyry แทน Placidus และแนบ "fallbackFrom": "placidus" ในผลนั้น (แม้ระบุ Placidus เองก็เช่นกัน) | |
minorAspects | boolean | รวมเซมิเซ็กซ์ไทล์ (30°) · เซมิสแควร์ (45°) · เซสควิควอดเรต (135°) · ควินคันซ์ (150°) (ผังกำเนิด · ซินแนสทรี) ค่าเริ่มต้น false — เฉพาะ 5 มุมหลัก | |
orbs | string | ตารางออร์บของผังกำเนิด · ซินแนสทรี: leo1928 (ค่าเริ่มต้น — กุมและเล็ง อาทิตย์–จันทร์ 12° อาทิตย์/จันทร์–ดาวเคราะห์ 10° ดาวเคราะห์ด้วยกัน 8° สแควร์ · ไตรน์ 8° เซ็กซ์ไทล์ 7° เซมิสแควร์ · เซสควิ 4° เซมิเซ็กซ์ไทล์ · ควินคันซ์ 2°) · heindel1919 (มุมหลักค่าเดียว 6° แบบอนุรักษ์) | |
node | string | โหนดที่ Nn (โหนดเหนือ) · Sn (โหนดใต้ = โหนดเหนือ + 180°) ในคีย์กฎจะใช้: mean (ค่าเริ่มต้น โหนดเฉลี่ย) · true (โหนดจริง) ใช้กับ node_sign Nn_… · Sn_… ของ features และคีย์กุมโหนด (Mo_Nn_cj · Nn_Asc_cj ฯลฯ) คีย์ MNn_… · TNn_… ออกมาทั้งคู่ไม่ว่าค่านี้จะเป็นอะไร | |
lang | string | ภาษาของ signName (ชื่อราศี) — ko (ค่าเริ่มต้น) · en · ja · th | |
timing | object | หากส่งมา จะคำนวณทรานซิต + Secondary Progression แล้วใส่ใน timing ของการตอบกลับ ดูตารางด้านล่าง | |
partner | object | อินพุตการเกิดของอีกฝ่าย (ฟิลด์เดียวกับข้างต้น ยกเว้น lang) หากส่งมา จะใส่มุม · ความสัมพันธ์ราศีระหว่างสองคนใน synastry ของการตอบกลับ หากมีเวลาเกิดและพิกัด (birthLatitude · birthLongitude) ของอีกฝ่าย จะคำนวณลัคนา (Asc) · กลางฟ้า (MC) ของอีกฝ่ายแล้วใส่ในมุมไขว้ด้วย |
ภายในบล็อก timing:
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
orbDegrees | number | O | ออร์บ (องศา) ของมุมทรานซิต→กำเนิด และโปรเกรสชัน→กำเนิด 0.5~10 ใช้ค่าเดียวกันกับทุกคู่ดาว (เฉพาะ 5 มุมหลัก) |
at | string | เวลาที่ต้องการดู YYYY-MM-DD (= 00:00 UTC ของวันนั้น) หรือวันเวลาที่มีค่าชดเชย (2026-10-11T09:00:00+09:00, ...Z) วันเวลาที่ไม่มีค่าชดเชยได้ 400 หากละไว้คือตอนนี้ | |
progressions | boolean | คำนวณ Secondary Progression (ค่าเริ่มต้น true) | |
yearLength | string | ความยาว 1 ปีที่ใช้แปลงเวลาที่ผ่านไปเป็น "กี่ปีของชีวิต": tropical (365.24219 วัน ค่าเริ่มต้น) · julian (365.25 วัน) |
ตัวอย่างคำขอ 1 — พื้นฐาน (เฉพาะผังกำเนิด)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["placidus", "whole_sign"]
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "birthLatitude": 37.5665, "birthLongitude": 126.978, "minorAspects": true, "lang": "en"}'
ตัวอย่างการตอบกลับ 1 (ตัดตอน ผลลัพธ์จริงของเอนจิน)
{
"success": true,
"data": {
"natal": {
"utc": "1990-05-15T05:30:00.000Z",
"timePrecision": "exact",
"timeKnown": true,
"zodiac": "tropical",
"lang": "ko",
"bodies": [
{ "id": "Sun", "longitude": 54.1347, "sign": "Taurus", "signKey": "tau", "signName": "황소자리", "degreeInSign": 24.1347, "speed": 0.9643, "retrograde": false, "dignities": [], "house": { "placidus": 9, "whole_sign": 9 } },
{ "id": "Moon", "longitude": 293.8244, "sign": "Capricorn", "signKey": "cap", "signName": "염소자리", "degreeInSign": 23.8244, "speed": 12.2943, "retrograde": false, "dignities": ["det"], "house": { "placidus": 4, "whole_sign": 5 } },
...
],
"nodes": [
{ "id": "MeanNode", "longitude": 311.3535, "sign": "Aquarius", "signName": "물병자리", "speed": -0.0529,
"south": { "longitude": 131.3535, "sign": "Leo", "signName": "사자자리", ... } },
{ "id": "TrueNode", ... }
],
"angles": { "asc": 173.5996, "mc": 82.8067, "dsc": 353.5996, "ic": 262.8067,
"ascSign": { "sign": "Virgo", "signName": "처녀자리", ... }, "mcSign": { ... }, "dscSign": { ... }, "icSign": { ... }, "polar": false },
"anglesOmitted": null,
"houseSystems": ["placidus", "whole_sign"],
"houses": {
"placidus": { "cusps": [173.5996, 199.6989, 229.8749, ...], "bodies": { "Sun": 9, "Moon": 4, "Jupiter": 10, ... } },
"whole_sign": { "cusps": [150, 180, 210, ...], "bodies": { "Sun": 9, "Moon": 5, ... } }
},
"housesExcluded": [],
"orbs": "leo1928",
"minorAspects": false,
"aspects": [
{ "a": "Jupiter", "b": "Uranus", "type": "opposition", "code": "op", "key": "Ju_Ur_op", "separation": 179.6986, "orb": 0.3014, "orbLimit": 8, "strength": "exact", "applying": false, "outOfSign": false },
{ "a": "Sun", "b": "Moon", "type": "trine", "code": "tr", "key": "Su_Mo_tr", "orb": 0.3104, "orbLimit": 8, "strength": "exact", "applying": true, "outOfSign": false },
...
],
"dignities": { "Sun": [], "Moon": ["det"], "Mercury": [], "Venus": ["det"], "Mars": [], "Jupiter": ["exa"], "Saturn": ["dom"] },
"moonSignUncertain": false,
"features": [
{ "type": "planet_sign", "key": "Su_tau" },
{ "type": "dignity", "key": "Mo_det" },
{ "type": "planet_retrograde", "key": "Me_rx" },
{ "type": "planet_house", "key": "Su_h9", "system": "placidus" },
{ "type": "aspect", "key": "Su_Mo_tr", "strength": "exact", "applying": true, "orb": 0.31 },
{ "type": "meta", "key": "time_known" },
...
]
},
"readings": {
"dignities": [
{ "key": "Mo_det", "text": "달이 염소자리에서 손상 자리에 있으면 감정을 바로 내보이기보다 책임과 일의 질서 속에서 조심스럽게 다루는 경향이 있어요. ...", "lang": "ko" },
{ "key": "Ve_det", ... }, { "key": "Ju_exa", ... }, { "key": "Sa_dom", ... }
],
"aspects": [
{ "key": "Su_Mo_tr", "text": "태양과 달의 트라인은 의지와 정서가 같은 곳을 바라봐, 스스로 길을 내며 생활 전반을 고르게 꾸려 가는 힘이 실려요. ...", "lang": "ko", "deviation": 0.31 },
{ "key": "Su_Sa_tr", ... }, { "key": "Mo_Sa_cj", ... }, ...
],
"lang": "ko"
},
"readingsUnavailable": false,
"costPoints": 50
}
}
หากไม่ส่ง timing · partner การตอบกลับจะไม่มีคีย์ timing · synastry เลย
bodies[]: ดวงอาทิตย์ · ดวงจันทร์ · ดาวพุธ · ดาวศุกร์ · ดาวอังคาร · ดาวพฤหัสบดี · ดาวเสาร์ · ดาวยูเรนัส · ดาวเนปจูน · ดาวพลูโตlongitudeคือลองจิจูดสุริยวิถี (0° = จุดวสันตวิษุวัต ทรอปิคัล)speedคือองศา/วัน — ถ้าติดลบretrograde: trueแต่ละดาวมีsignName(ชื่อราศีในภาษาlang) ·degreeInSign(องศาภายในราศี 0~30°) ·house(หมายเลขเรือนตามระบบเรือนที่ขอ ค่าเดียวกับhouses[ระบบ].bodies— หากไม่ได้คำนวณเรือนเป็น{}) แนบอยู่ จึงวาดตารางผังได้จากข้อมูลนี้อย่างเดียวdignities: ศักดิ์ของดวงอาทิตย์~ดาวเสาร์ (domเกษตร ·exaอุจจ์ ·detประ ·falนิจ ทุกสถานะที่ตรง) เป็นค่าเดียวกับbodies[].dignitiesnodes[]:MeanNode(โหนดเฉลี่ย) ·TrueNode(โหนดจริง) = โหนดเหนือ,south= โหนดใต้ (+180°)angles: ASC · MC · DSC · IC คำนวณเฉพาะเมื่อมีทั้งเวลาเกิด (exact/approximate) และพิกัด หากไม่มีจะเป็นnullและanglesOmittedจะบอกเหตุผล (time_unknown|coordinates_missing) ในกรณีนี้จะไม่คำนวณเรือนด้วยhousesจึงเป็น{}houses:cuspsตามระบบที่ขอ (ลองจิจูดสุริยวิถีที่เริ่มเรือน 1~12) +bodies(หมายเลขเรือนของแต่ละดาว)houseSystems·houses: ระบบที่คำนวณจริง ที่สถานที่เกิดในเขตขั้วโลก (angles.polar= ละติจูดประมาณ 66.56° ขึ้นไป) Placidus อาจไม่มีนิยาม จึงคำนวณแบบ Porphyry แทนแล้วแสดงด้วยhouses.porphyry.fallbackFrom = "placidus"(ไม่เปลี่ยนแบบเงียบๆ) การตัดสินใช้ละติจูดของสถานที่เกิด สถานที่เกิดเดียวกันจึงได้ระบบเดิมเสมอไม่ว่าเวลาใดhousesExcludedคือระบบอื่นที่คำนวณไม่ได้และเหตุผล (ไม่ใช่การตอบกลับข้อผิดพลาด)aspects[]:orb= องศาที่เบี่ยงจากมุมตรงstrength=exact(ภายใน 2°) ·close(ภายในครึ่งหนึ่งของขีดจำกัด) ·wideapplying=trueหากกำลังเข้าหามุมตรง (ไม่ทราบเป็นnull)outOfSign= มุมที่ข้ามเส้นแบ่งราศี (อ่านให้อ่อนลงหนึ่งระดับ)moonSignUncertain: เมื่อไม่ทราบเวลา หากราศีจันทร์เปลี่ยนภายในวันนั้นจะเป็นtrue— ในกรณีนี้planet_signของดวงจันทร์ในfeaturesจะมี"uncertain": trueแนบมาreadings(รวมเสมอ ไม่มีค่าบริการเพิ่ม): ย่อหน้าการอ่านที่ HRUM เขียนไว้ล่วงหน้าdignities[]= ศักดิ์ของดาว (ดวงอาทิตย์~ดาวเสาร์ ดาวละหนึ่งสถานะที่แรงที่สุด)aspects[]= มุมระหว่างดาวกำเนิด เรียงตามออร์บจากแคบไปกว้าง แต่ละย่อหน้ามีkey(คีย์เดียวกับfeatures·aspects[].key) ·text·lang(ภาษาจริงของย่อหน้า — หากไม่มีย่อหน้าในภาษาที่ขอเป็นko) ·deviation(เฉพาะมุม องศาที่เบี่ยงจากมุมตรง) แนบเฉพาะคีย์ที่มีย่อหน้าเขียนไว้ล่วงหน้า ที่เหลือจะข้าม (ไม่แต่งขึ้นทันที) — มุมที่มีดาวยูเรนัส · เนปจูน · พลูโตเกี่ยวข้องและมุมรองไม่มีย่อหน้าจึงไม่รวม หากไม่มีเวลาเกิด มุมที่มีดวงจันทร์เกี่ยวข้องจะไม่แนบ และหากราศีจันทร์ไม่แน่นอน ศักดิ์ของดวงจันทร์จะไม่แนบ ตัวอย่างข้างต้น (1990-05-15 14:30 โซล) คือ มุมสัมพันธ์ 7 จาก 16 รายการ + ศักดิ์ 4 รายการ = 11 ย่อหน้าreadingsUnavailable: เป็นtrueเมื่อดึงย่อหน้าการอ่านไม่ได้ — ในกรณีนี้ผลการคำนวณผังยังมาตามเดิมreadingsเป็นอาร์เรย์ว่าง และราคา (₩50) ก็เท่าเดิมfeatures[]: คีย์สำหรับจับคู่กับ DB กฎplanet_signSu_ari·planet_retrogradeMe_rx·dignityMa_dom·node_signMNn_leo·TNn_leo·Nn_leo·Sn_aqu(Nn·Snคือโหนดตามตัวเลือกnode) ·angle_signAsc_sco·planet_houseVe_h7(+system) ·aspectSu_Mo_cj(โหนดมีเฉพาะการกุม 3° —Mo_Nn_cj·Sa_Sn_cj·Nn_Asc_cjคู่ที่มีลัคนาเฉพาะเมื่อมีเวลาเกิด) ·house_cusp_signh12_ari(คัสป์เรือน 12 อยู่ราศีเมษ) ·house_emptyh6(เรือนที่ไม่มีดาวเคราะห์ใดใน 10 ดวงเลย) ·house_ruler_househ1_h7(เจ้าเรือน 1 อยู่เรือน 7) ·house_ruler_signh7_lib(เจ้าเรือน 7 อยู่ราศีตุลย์) — เจ้าเรือนคือเจ้าราศีแบบดั้งเดิมของราศีคัสป์ (7 ดาว ดวงอาทิตย์~ดาวเสาร์) ·planet_risingJu(เรือน 1 หรืออยู่ในเรือน 12 ภายใน 6° จากลัคนา) — ห้าประเภทนี้มี+systemและมีเฉพาะเมื่อมีเวลาเกิดและพิกัด ·planet_solarVe_cazimi(ภายใน 17′ จากดวงอาทิตย์) /Me_combust(17′~8°30′ ราศีเดียวกับดวงอาทิตย์) /Ma_beams(นอกนั้นภายใน 17°) — สามระดับไม่ซ้อนกัน ·moon_phasewaxing·waning·metatime_known(มีเวลา —exact·approximate) /time_hour_level(เพิ่มเมื่อเป็นapproximate) /time_unknownแต่ละคีย์ (aspect·transit·progressed·syn_aspect) จะมีorb(องศาที่เบี่ยงจากมุมตรง ทศนิยม 2 ตำแหน่ง) และ"outOfSign": trueเฉพาะเมื่อมุมข้ามเส้นแบ่งราศี — เป็นค่าที่ใช้จับคู่กับแอตทริบิวต์ของคีย์กฎ[orb=…]·[outOfSign=true]หากไม่ทราบเวลาเกิด มุมกำเนิดที่มีดวงจันทร์เกี่ยวข้องจะมี"uncertain": trueแนบมา ตัวย่อดาวSu Mo Me Ve Ma Ju Sa Ur Ne PlโหนดMNn TNn Nn Snรหัสมุมcj(0°)sx(60°)sq(90°)tr(120°)op(180°) · มุมรองssx(30°)ssq(45°)sqq(135°)qcx(150°)
ตัวอย่างคำขอ 2 — รวม timing (ทรานซิต + Secondary Progression)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["whole_sign"],
"timing": { "at": "2026-10-11T09:00:00+09:00", "orbDegrees": 3, "yearLength": "tropical" }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "timing": {"orbDegrees": 2, "progressions": false}}'
ตัวอย่างการตอบกลับ 2 (ตัดตอน natal มีรูปแบบเดียวกับตัวอย่าง 1)
{
"success": true,
"data": {
"natal": { ... },
"timing": {
"at": "2026-10-11T00:00:00.000Z",
"orbDegrees": 3,
"natalPoints": ["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Asc", "MC"],
"transits": {
"bodies": [ { "id": "Sun", "longitude": 197.6966, "sign": "Libra", "signName": "천칭자리", "speed": 0.9889, "retrograde": false, ... }, ... ],
"aspects": [
{ "a": "Mars", "b": "Mercury", "type": "square", "key": "tMa_nMe_sq", "orb": 0.6358, "orbLimit": 3, "strength": "exact", "applying": true, "outOfSign": false },
...
]
},
"progressions": {
"yearLength": "tropical",
"yearLengthDays": 365.24219,
"ageYears": 36.4081,
"instant": "1990-06-20T15:17:39.048Z",
"bodies": [ { "id": "Sun", "longitude": 89.0352, "sign": "Gemini", "signName": "쌍둥이자리", ... }, ... ],
"aspects": [
{ "a": "Uranus", "b": "Mercury", "type": "trine", "key": "pUr_nMe_tr", "orb": 0.0862, "orbLimit": 3, "strength": "exact", "applying": false, "outOfSign": false },
...
]
},
"features": [
{ "type": "transit", "key": "tMa_nMe_sq", "strength": "exact", "applying": true, "orb": 0.64 },
{ "type": "progressed", "key": "pUr_nMe_tr", "strength": "exact", "applying": false, "orb": 0.09 },
...
]
},
"readings": { ... }, "readingsUnavailable": false,
"costPoints": 50
}
}
- เป้าหมายทรานซิต (
natalPoints): ดาวกำเนิด 10 ดวง + ลัคนา (Asc) · กลางฟ้า (MC) หากมีเวลาเกิด · พิกัด คีย์มีคำนำหน้าt(ทรานซิต) ·n(กำเนิด) —tSa_nSu_cj= ดาวเสาร์ทรานซิตกุมดวงอาทิตย์กำเนิด transit_housetSa_h7(ดาวเสาร์ทรานซิตอยู่เรือน 7 กำเนิด) ·progressed_housepMo_h4(ดวงจันทร์โปรเกรสอยู่เรือน 4 กำเนิด): ดาวเคราะห์อย่างละ 10 ดวง เรือนกำเนิดใช้ระบบเริ่มต้น (Placidus หากเป็นเขตขั้วโลกใช้ Porphyry +"fallbackFrom": "placidus") และคีย์จะมี"system"แนบมา — แม้ส่งhouseSystemsต่างไป สองคีย์นี้ก็อิงระบบเริ่มต้น หากไม่มีเวลาเกิดหรือพิกัดจะไม่ออกมา- มุมโปรเกรส→กำเนิดมีเป้าหมายเฉพาะดาวเคราะห์กำเนิด คีย์
pSu_nJu_tr= ดวงอาทิตย์โปรเกรสทำมุมไตรน์กับดาวพฤหัสบดีกำเนิดinstantคือเวลาของท้องฟ้าที่ใช้เป็นผังโปรเกรส (เวลาเกิด +ageYearsวัน) - หาก
progressions: falsetiming.progressionsจะเป็นnullหากละyearLengthจะเป็นtropical(365.24219 วัน) - เมื่อเปิด
progressionsอยู่ หากtiming.atมาก่อนเวลาเกิดจะได้ 400at_before_birth(ไม่คิดค่าบริการ) - หากไม่ทราบเวลา จะตั้งผังกำเนิดตามเที่ยงวัน คีย์ที่มีเป้าหมายเป็นดวงจันทร์กำเนิด (
…_nMo_…) และคีย์ดวงจันทร์โปรเกรส (pMo_…) จะมี"uncertain": trueแนบมา (ดวงจันทร์โปรเกรสรับตำแหน่งดวงจันทร์กำเนิดมาตามเดิม จึงแกว่งเท่ากับเกณฑ์เที่ยงวัน)
ตัวอย่างคำขอ 3 — รวม partner (ซินแนสทรี)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["whole_sign"],
"partner": { "birthDate": "1992-11-03", "birthTime": "08:10", "birthTimePrecision": "exact", "birthLatitude": 35.1796, "birthLongitude": 129.0756 }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "partner": {"birthDate": "1992-11-03"}}'
ตัวอย่างการตอบกลับ 3 (ตัดตอน natal มีรูปแบบเดียวกับตัวอย่าง 1)
{
"success": true,
"data": {
"natal": { ... },
"synastry": {
"partner": {
"utc": "1992-11-02T23:10:00.000Z",
"timePrecision": "exact",
"timeKnown": true,
"moonSignUncertain": false,
"bodies": [ { "id": "Sun", "longitude": 220.7903, "sign": "Scorpio", "signName": "전갈자리", "speed": 1.0016, "retrograde": false, "dignities": [], ... }, ... ],
"angles": { "asc": 252.31, "mc": 175.86, "ascSign": { "sign": "Sagittarius", "signName": "사수자리", ... }, "mcSign": { "sign": "Virgo", "signName": "처녀자리", ... } },
"anglesOmitted": null
},
"orbs": "leo1928",
"minorAspects": false,
"aspects": [
{ "a": "Moon", "b": "Mars", "type": "opposition", "code": "op", "key": "aMo_bMa_op", "orb": 0.2993, "orbLimit": 10, "strength": "exact", "applying": null, "outOfSign": false },
{ "a": "Neptune", "b": "Uranus", "type": "conjunction", "code": "cj", "key": "aNe_bUr_cj", "orb": 0.3898, "orbLimit": 8, "strength": "exact", "applying": null, "outOfSign": false },
...
],
"features": [
{ "type": "syn_aspect", "key": "aMo_bMa_op", "strength": "exact", "orb": 0.3 },
{ "type": "syn_aspect", "key": "aNe_bUr_cj", "strength": "exact", "orb": 0.39 },
{ "type": "astro_syn", "key": "Su_Mo_se" },
{ "type": "syn_sign", "key": "aAsc_bAsc_es" },
...
]
},
"readings": { ... }, "readingsUnavailable": false,
"costPoints": 50
}
}
- คำนำหน้าคีย์
a= ผู้ขอเองb=partneraVe_bMa_cj= ดาวศุกร์ของตัวเองกุมดาวอังคารของอีกฝ่าย ดูครบทุกคู่ระหว่างดาวของตัวเอง 10 ดวง (+ลัคนา · กลางฟ้า) × ดาวของอีกฝ่าย 10 ดวง (+ลัคนา · กลางฟ้า) (มีทิศทางaSu_bMoกับaMo_bSuจึงเป็นคนละคีย์) - ลัคนา (
Asc) · กลางฟ้า (MC) คำนวณเฉพาะเมื่อบุคคลนั้นมีทั้งเวลาเกิดและพิกัด (กฎเดียวกับตัวเอง ของอีกฝ่ายอยู่ที่synastry.partner.angles/anglesOmitted) มุมไขว้ที่มีมุมหลักเกี่ยวข้องดูเฉพาะการกุม · เล็ง 6° แต่เฉพาะการกุมระหว่างลัคนาด้วยกัน (aAsc_bAsc_cj) ให้ถึง 17° (ปโตเลมี "Tetrabiblos" — หากลัคนาสองคนอยู่ภายใน 17° ความผูกพันจะแข็งแรง กฎ[orb=17]) องศาที่ห่างจริงมาในorbมุมหลักจะคำนวณเมื่อเวลาของผู้ที่มีมุมนั้นแน่นอนเท่านั้น จุดตก · ก้นฟ้าเป็นด้านตรงข้ามของลัคนา · กลางฟ้า จึงไม่ออกคีย์แยก astro_syn: ความสัมพันธ์ราศีที่แรงที่สุด 2 รายการ จาก 6 คู่คลาสสิก (ดวงอาทิตย์–ดวงจันทร์ ดาวศุกร์–ดาวอังคาร ดวงจันทร์–ดาวศุกร์ ดวงอาทิตย์–ดาวศุกร์ ดวงจันทร์–ดาวอังคาร ดาวศุกร์–ดาวเสาร์) รวมสองทิศทางเป็นคีย์เดียว (Su_Mo_se= ดวงอาทิตย์ของฝ่ายหนึ่งกับดวงจันทร์ของอีกฝ่ายเป็นธาตุเดียวกัน)syn_sign: ความสัมพันธ์ราศีของทุกคู่จุดของตัวเอง × จุดของอีกฝ่าย (aAsc_bAsc_ss) หากทั้งสองคนมีเวลาเกิดเป็นexactจะรวมจุดโชคลาภ (PoFสลับสูตรกลางวัน/กลางคืน) เป็นจุดด้วย (aPoF_bPoF_ss) — จุดโชคลาภเคลื่อนไปพร้อมลัคนาประมาณ 1° ทุก 4 นาที จึงไม่ออกในระดับชั่วโมง (approximate) หรือเมื่อไม่ทราบเวลา รหัสความสัมพันธ์ss(ราศีเดียวกัน) ·op(ตรงข้าม) ·se(ธาตุเดียวกัน) ·es(ธาตุเกื้อหนุน) ·sm(ลักษณะเดียวกัน) ·ef(ธาตุเสียดทาน) ·nt(ไม่เกี่ยวข้อง)- ตารางออร์บและการรวมมุมรองใช้
orbs·minorAspectsเดียวกับผังกำเนิด เป็นมุมระหว่างผังกำเนิดสองผังจึงไม่มีการเข้าหา · แยกจากapplyingจึงเป็นnullเสมอ - หากฝ่ายใดฝ่ายหนึ่งไม่ทราบเวลาเกิด ผังของคนนั้นจะอิงเที่ยงวัน มุมที่มีดวงจันทร์ของคนนั้นเกี่ยวข้องจะมี
"uncertain": trueในfeatures(ดวงจันทร์เคลื่อนวันละประมาณ 13° จึงแกว่งกว้างกว่าออร์บ) มุมที่จับคู่กับมุมหลักของอีกฝ่าย (aAsc_bMo_…ทิศทางกลับaMo_bAsc_…) ก็เช่นกัน - ไม่คำนวณเรือนของอีกฝ่าย (ไม่มีการซ้อนเรือนของซินแนสทรี)
ค่าเริ่มต้นและค่าที่ต้องเลือกเอง
- ระบบเรือน (ค่าเริ่มต้น
placidus): ระบบที่พจนานุกรมปี 1819 · 1929 ระบุว่า "ใช้กันทั่วไป" ที่สถานที่เกิดในเขตขั้วโลกจะใช้ Porphyry แทนและแสดงด้วยfallbackFromหากต้องการระบบอื่นให้เลือกด้วยhouseSystems - ความยาว 1 ปีของโปรเกรสชัน (ค่าเริ่มต้น
tropical365.24219 วัน): 1 ปีแบบ "วันเกิด→วันเกิดถัดไป" ตามตำรา ความต่างกับปีจูเลียน (julian) คือเวลาโปรเกรสประมาณ 2.5 นาทีเมื่ออายุ 80 ปี - ออร์บของทรานซิต · โปรเกรสชัน (
timing.orbDegreesจำเป็นเมื่อส่งtiming): ตำราแต่ละเล่มต่างกัน (ช่วงก่อนมุมตรง 8° กับ 10°) หากเว้นว่างจะได้ 400 - มุมกำเนิดที่มีดาวพลูโต · โหนด · มุมหลักเกี่ยวข้องไม่อยู่ในตารางออร์บเริ่มต้น: เป็นจุดที่ตารางออร์บของ Leo (1928) · Heindel (1919) ไม่ได้ครอบคลุม (ดาวพลูโตค้นพบในปี 1930) ดังนั้น
aspectsของผังกำเนิดจึงไม่มีจุดเหล่านี้ (แต่มีในตำแหน่ง · เรือน) เฉพาะมุมไขว้ของมุมหลักในซินแนสทรีที่ดูการกุม · เล็ง 6° (เฉพาะการกุมระหว่างลัคนา 17°)
สิ่งที่ไม่ได้ให้บริการ
- ศักดิ์รอง (ตรีภาค · เขต term · หน้า face) การรับกัน (reception) จุดโชคลาภของผังกำเนิด (ใช้เฉพาะใน
syn_signของซินแนสทรี) ศักดิ์ของดาวยูเรนัส · เนปจูน · พลูโต พาราเลล · จุดกึ่งกลาง - มุมหลักแบบโปรเกรส (ASC · MC โปรเกรส) — ตำราไม่ได้กำหนดวิธีไว้
- DSC · IC ให้ค่า แต่ไม่ออกคีย์
features(โหนดใต้ออกเป็นคีย์Sn) - คีย์ข้างขึ้นข้างแรมแบบเดือนดับ · เพ็ญ · ขึ้นครึ่งดวง · แรมครึ่งดวง (
moon_phaseมีเฉพาะwaxing·waning) ดวงอาทิตย์ตะวันออก · ตะวันตก (oriental · occidental) คีย์มุมหลักแบบโปรเกรส - การซ้อนเรือนของซินแนสทรี
ราคา
- ₩50 ต่อครั้งเท่ากับปฏิทินหมื่นปี — แม้เพิ่มบล็อก
timing·partnerและไม่ว่าระบบเรือน · การรวมมุมรองจะเป็นอย่างไร ก็ ₩50 ครั้งเดียวเหมือนเดิมcostPointsในการตอบกลับคือยอดที่หักครั้งนี้ (₩) endpoint ในบันทึกการใช้งานคือastrology - หักเฉพาะเมื่อคำนวณสำเร็จ อินพุตผิดพลาด (400) · ยอดคงเหลือไม่พอ (402) ไม่คิดค่าบริการ
- หากเรียกขณะที่ยังไม่เปิด จะได้ 404
astrology_not_enabled(ไม่คิดค่าบริการ)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | astrology_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 400 | at_before_birth | timing.at มาก่อนเวลาเกิด (เมื่อเปิดการคำนวณโปรเกรสชัน) |
| 402 | (ไม่มี) | ยอดคงเหลือน้อยกว่าค่าเรียก — API นี้ไม่ตรวจยอดคงเหลือก่อนเรียก จึงได้ 402 ที่ไม่มีรหัส |
API กราฟดวงชะตา
คำนวณกระแสที่วัยจร 10 ปี · ดวงรายปี · ดวงรายเดือนซ้อนทับบนผังดวงจากซาจูของบุคคลหนึ่ง แล้วคืนเป็นตัวเลขสำหรับกราฟและรายการความสัมพันธ์ ครั้งละหนึ่งคน ไม่ใช้ LLM ค่าแกนตั้งคือ"คะแนนฝั่งก้านวันเกิดเมื่อซ้อนอักษรของดวงจร" — นำคะแนนรวมความแข็ง-อ่อนของผังดวงมาบวกส่วนที่ให้คะแนนอักษรดวงจรแต่ละตัวด้วยตารางคะแนนต่ออักษรเดียวกับผังดวง (เกื้อหนุน · ควบคุม · ก้านแฝง · ราก) แล้วตัดที่ ±100 ไม่ได้วัดความดีร้ายของดวง (R-SAJU-UN-034) ชื่อดวงแข็ง · สมดุล · ดวงอ่อนใช้ตามผังดวงเดิม และไม่ตั้งใหม่ตามดวงจร
ราคา: ₩50 ต่อครั้ง (เท่ากับปฏิทินหมื่นปี ขยายช่วง · ดวงรายเดือนก็ราคาเดิม) การตอบกลับที่ล้มเหลวอย่าง 400 ไม่คิดค่าบริการ
ตัวเลขทั้งหมดเป็นค่าจากเอนจินซาจูกลางตัวเดียวกับ INTA เวลาเกิดอ่านเป็นนาฬิกาตามประวัติเวลามาตรฐานเกาหลี (1954~61 UTC+8:30 นำเวลาออมแสงมาใช้อัตโนมัติ) แล้วเทียบกับจุดเปลี่ยนฤดู จึงได้ผลเดียวกันไม่ว่าเขตเวลาของเซิร์ฟเวอร์จะเป็นอะไร
สถานที่เกิด (เพิ่มเมื่อ 2026-10-15 saju-flow-5): รับฟิลด์เดียวกับ API ปฏิทินหมื่นปี (birthLatitude · birthLongitude · country · birthTimePrecision) และปรับเวลาสุริยะจริงด้วยวิธีเดียวกัน หากเวลาเกิดอยู่ใกล้เส้นแบ่งเสายาม · เสาวัน · จุดเปลี่ยนฤดู การปรับจะเปลี่ยนอักษรของผังดวง จึงต้องส่งตำแหน่งที่ส่งให้ปฏิทินหมื่นปีมาที่กราฟดวงชะตาด้วยตามเดิม ผลทั้งสองจึงจะใช้ผังดวงเดียวกัน หากไม่ส่งตำแหน่ง จะคำนวณด้วยการจัดการเริ่มต้นเดียวกับเมื่อเรียกปฏิทินหมื่นปีโดยไม่มีตำแหน่ง (ตอนนี้ไม่ปรับ) และแจ้งค่าเริ่มต้นนั้นใน assumedLocation ของการตอบกลับ
POST /api/v1/partners/v1/saju-flow
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
birthDate | string | O | YYYY-MM-DD (1900~2100) วันที่ตาม calendar |
birthTime | string | null | HH:mm หากไม่มีจะถือว่าไม่ทราบเสายาม — คำนวณตาม 6 อักษร และ hourKnown: false | |
calendar | string | O | solar · lunar (จันทรคติจะแปลงเป็นสุริยคติแล้วคำนวณ) |
isLeapMonth | boolean | เดือนอธิกมาสตามจันทรคติ (ค่าเริ่มต้น false) | |
gender | string | null | male · female หากไม่มีจะไม่มีชั้นวัยจร 10 ปี (daeun: [], daeunIndex: null) | |
timezone | string | รับเฉพาะ Asia/Seoul | |
birthLatitude · birthLongitude | number | พิกัดสถานที่เกิด (ต้องส่งทั้งสองค่า) ฟิลด์เดียวกัน · กฎเดียวกับ API ปฏิทินหมื่นปี — ปรับเวลาสุริยะจริงด้วยลองจิจูด และกราฟดวงชะตาก็วาดบนผังดวงที่ปรับแล้วซึ่งปฏิทินหมื่นปีคืนให้ หากส่งค่าเดียวจะได้ 400 INVALID_LOCATION หากไม่ส่งจะใช้การจัดการเริ่มต้นของปฏิทินหมื่นปี (ตอนนี้ไม่ปรับ) และแจ้งด้วย assumedLocation | |
country | string | รหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับด้วยลองจิจูดตัวแทนของประเทศนั้น (เหมือนปฏิทินหมื่นปี) | |
birthTimePrecision | string | exact · approximate · estimated · unknown ปรับเฉพาะเมื่อเป็น exact (หากส่งตำแหน่ง ค่าเริ่มต้นคือ exact) หากส่งค่าที่ไม่ใช่ exact จะคำนวณโดยไม่ปรับเวลาสุริยะจริง ผู้ที่เกิดในช่วงเวลาออมแสงของเกาหลีจะลบ 1 ชั่วโมงแล้วอ่านเป็นเวลามาตรฐานเหมือนปฏิทินหมื่นปี (2026-10-16) | |
range | object | O | { "fromYear", "toYear" } ช่วงของดวงรายปี (ปีสุริยคติ สูงสุด 101 ปี) แนะนำให้ดึงช่วงปีเกิด ~ ปีเกิด+100 ไว้ครั้งเดียว แล้วตัดใช้บนหน้าจอ |
monthsOfYear | integer | null | ปีซาจูที่จะคำนวณดวงรายเดือน 12 ช่อง (ตั้งแต่ลี่ชุนของปีนั้นจนถึงก่อนลี่ชุนของปีถัดไป) หากละไว้คือปีซาจูที่ตอนนี้ (เวลาเกาหลี) อยู่ — ช่วง 1 มกราคม~ก่อนลี่ชุนคือปีก่อน หากเป็น null จะไม่มีชั้นดวงรายเดือน (months: []) | |
lang | string | ko · en · ja · th ค่าในการตอบกลับเป็นรหัสที่ไม่ขึ้นกับภาษา (การอ่านก้าน-กิ่งเป็นฮันกึล · ธาตุทั้งห้า · ชื่อความสัมพันธ์) ตอนนี้ผลจึงเหมือนกัน รายการทั้งหมดดูที่ ค่าที่ใช้ได้ > ค่ารหัสที่ไม่ขึ้นกับภาษา |
ตัวอย่างคำขอ
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"calendar": "solar",
"gender": "male",
"timezone": "Asia/Seoul",
"range": { "fromYear": 1990, "toYear": 2090 },
"monthsOfYear": 2026
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/saju-flow \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: chart-123:flow:2026" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "calendar": "solar", "gender": "male", "timezone": "Asia/Seoul", "range": {"fromYear": 1990, "toYear": 2090}, "monthsOfYear": 2026}'
ตัวอย่างการตอบกลับ (ตัดตอน ผลลัพธ์จริงของเอนจิน)
{
"success": true,
"data": {
"engineVersion": "saju-flow-6",
"kbVersion": "2026.10.11-7",
"hourKnown": true,
"natalAmbiguous": null,
"natal": {
"score": -37, "result": "중화", "level": "약약",
"breakdown": { "season": -30, "support": 36, "control": -28, "hidden": -5, "root": 5 },
"primaryYongshin": "토",
"shin": { "yongshin": "토", "huishin": "화", "gishin": "목", "gushin": "수", "hanshin": "금" },
"ruleIds": ["R-SAJU-STR-001", "R-SAJU-STR-018", "R-SAJU-STR-019", "R-SAJU-YONG-170"]
},
"daeun": [
{ "startYear": 1997, "endYear": 2006, "startAge": 7,
"chars": [
{ "pos": "stem", "char": "임", "hanja": "壬", "ohaeng": "수", "sipsin": "식신", "shinRole": "gushin",
"share": { "support": 0, "control": -8, "hidden": 0, "root": 0, "total": -8 } },
{ "pos": "branch", "char": "오", "hanja": "午", "ohaeng": "화", "sipsin": "정관", "shinRole": "huishin",
"share": { "support": 0, "control": -10, "hidden": -5, "root": 0, "total": -15 } }
],
"delta": -23, "line": { "value": -60, "clamped": false },
"relations": [
{ "type": "자형", "from": "daeun", "with": "yearBranch", "a": "오", "b": "오", "ruleId": "R-SAJU-REL-044", "decisionRuleId": "R-SAJU-UN-036" },
{ "type": "육합", "from": "daeun", "with": "hourBranch", "a": "오", "b": "미", "ruleId": "R-SAJU-REL-015", "decisionRuleId": null }
],
"triples": [], "hapPulim": [ ... ] },
...
],
"years": [
{ "year": 2026, "daeunIndex": 2,
"chars": [ { "pos": "stem", "char": "병", "hanja": "丙", ... "share": { ..., "total": -10 } },
{ "pos": "branch", "char": "오", "hanja": "午", ... "share": { ..., "total": -15 } } ],
"delta": -25, "line": { "value": -33, "clamped": false },
"relations": [
{ "type": "천간합", "from": "seun", "with": "monthStem", "a": "병", "b": "신", "ruleId": "R-SAJU-REL-003", "decisionRuleId": null },
...
],
"withDaeun": [], "triples": [],
"hapPulim": [
{ "kind": "existing", "domain": "jiji", "pair": ["오", "미"], "status": "broken_by_dong",
"reasonCode": "branch_hap_broken", "params": { "incoming": "오", "origin": "seun" },
"triggeredBy": { "origin": "seun", "value": "오" },
"reasonFallback": "동기 오(seun) 도래 → 합반 깨짐" },
{ "kind": "new", "domain": "cheongan", "pair": ["병", "신"], "chartValue": "신", "incomingValue": "병", "incomingOrigin": "seun",
"reasonCode": "new_stem_hap", "params": { "incoming": "병", "origin": "seun", "partner": "신" },
"reasonFallback": "병(seun) + 원국 신 → 새 천간 합 형성" },
...
],
"ipchunNote": false },
...
],
"months": [
{ "index": 1, "startsAt": "2026-02-04T04:55:00+09:00",
"chars": [ { "pos": "stem", "char": "경", ... }, { "pos": "branch", "char": "인", ... } ],
"delta": 4,
"relations": [ { "type": "반합", "from": "wolun", "with": "yearBranch", "a": "인", "b": "오", "ruleId": "R-SAJU-REL-024", "decisionRuleId": "R-SAJU-UN-035" }, ... ] },
...
],
"compatInputs": {
"primaryYongshin": "토",
"surfaceElementCounts": { "목": 0, "화": 2, "토": 2, "금": 3, "수": 1 },
"surfaceAbsent": ["목"],
"hourKnown": true,
"ruleIds": ["R-SAJU-COMPAT-008", "R-SAJU-COMPAT-009", "R-SAJU-COMPAT-010"]
},
"caveats": ["R-SAJU-UN-028", "R-SAJU-PRAC-026", "R-SAJU-UN-034"],
"birthBeforeIpchun": false,
"assumedLocation": { "correction": "none" },
"costPoints": 0
}
}
วิธีอ่านฟิลด์
line: ค่าสะสม — วัยจร 10 ปีคือผังดวง + วัยจร 10 ปี ดวงรายปีคือผังดวง + วัยจร 10 ปีของปีนั้น + ดวงรายปี ทุกขั้นตัดที่ ±100 และถ้าถูกตัดจะเป็นclamped: true(R-SAJU-UN-033) ดวงรายเดือนไม่มีเส้นสะสม ให้เฉพาะส่วนของดวงเดือนนั้น (delta)share: การแยกส่วนของอักษรหนึ่งตัว (เกื้อหนุน · ควบคุม · ก้านแฝง · ราก) น้ำหนักของชั้นวัยจร 10 ปี · ดวงรายปี · ดวงรายเดือนเป็น 1:1:1 (R-SAJU-UN-030) รากของกิ่งดินดวงจรไม่มีเพดาน (R-SAJU-UN-031)shinRole: ชื่อ 5 ธาตุ (ธาตุช่วย · ธาตุยินดี · ธาตุต้องห้าม · ธาตุศัตรู · ธาตุว่าง R-SAJU-YONG-170) ของธาตุของอักษรนั้น — เป็นชื่อ ไม่ใช่คะแนน ทุกผังดวงจะมีตาราง 5 ธาตุ (ไม่มีnull)relations: รายการลงโทษ · ปะทะ · ประชุม · รวม ระหว่างอักษรดวงจรกับอักษรผังดวง (ไม่นำมาคิดคะแนน)ruleIdคือกฎตารางคู่decisionRuleIdคือกฎหลักฐานที่ใช้กับดวงจรด้วย (UN-035 ดวงรายเดือน UN-036 ลงโทษตัวเอง UN-037 รวมครึ่ง)withDaeunคือดวงรายปี ↔ วัยจร 10 ปีของปีนั้น หากไม่ทราบเสายามจะไม่ออกความสัมพันธ์กับเสายามtriples: กรณีที่อักษรวัยจร 10 ปี · ดวงรายปีเข้ามาแล้วครบสามอักษรของรวมสาม · รวมทิศร่วมกับผังดวง (R-SAJU-UN-037)hapPulim: การรวมในผังดวงที่อักษรวัยจร 10 ปี · ดวงรายปีไปกระทบ (การรวมถูกกระตุ้น · คลาย · แตก) และการรวมที่เกิดใหม่ (R-SAJU-HAP-021~027) ไม่รวมดวงรายเดือน ข้อความบนหน้าจอให้สร้างเองตามภาษาของแอปจากreasonCodeและparams(incomingอักษรดวงจรที่เข้ามาorigindaeun|seunและtarget·partnerเมื่อจำเป็น)reasonFallbackคือประโยคภาษาเกาหลีที่เอนจินเขียนไว้ซึ่งมีอยู่เสมอ ใช้แสดงแทนเฉพาะเมื่อได้reasonCodeที่แอปไม่รู้จัก ตอนนี้reasonCodeมี 7 แบบstem_hap_kept_jaenghap: การรวมก้านฟ้าในผังดวงคงอยู่ และอักษรดวงจรที่เป็นก้านหยางตัวเดียวกัน (incoming) เป็นการแย่งรวม (jaenghap) จึงแทรกไม่ได้stem_hap_kept_tuhap: การรวมก้านฟ้าในผังดวงคงอยู่ และอักษรดวงจรที่เป็นก้านหยินตัวเดียวกัน (incoming) เป็นการหึงรวม (tuhap) จึงแทรกไม่ได้branch_hap_gi: อักษรดวงจร (incoming) ปะทะอักษรหนึ่ง (target) ของการรวมหกในผังดวง ทำให้การรวมถูกกระตุ้น (hapgi)branch_hap_released: อักษรดวงจร (incoming) ลงโทษอักษรหนึ่งของการรวมหกในผังดวง ทำให้การรวมคลายbranch_hap_broken: อักษรเดียวกับอักษรหนึ่งของการรวมหกในผังดวง (incoming) เข้ามาเป็นดวงจร ทำให้การรวมแตกnew_stem_hap: ก้านฟ้าดวงจร (incoming) กับก้านฟ้าว่างในผังดวง (partner) เกิดการรวมก้านฟ้าใหม่new_branch_yukhap: กิ่งดินดวงจร (incoming) กับกิ่งดินผังดวง (partner) เกิดการรวมหกใหม่
startAge: เลขวัยจร (อายุวัยจรแรก) นับจำนวนวันตั้งแต่ 0 นาฬิกาของวันเกิด (วันที่เกาหลี) ถึงจุดเปลี่ยนฤดู ไม่รวมชั่วโมง · นาทีที่เกิด และปัดเศษโดย 3 วัน = 1 ปี (R-SAJU-UN-038) เป็นกฎที่อยู่ในบัญชีหลักตั้งแต่kbVersion2026.10.11-2ipchunNote: หากเวลาที่ดึงข้อมูล (เวลาเกาหลี) อยู่ก่อนลี่ชุนของปีนั้น จะเป็นtrueเฉพาะช่องของปีนี้ เป็นเครื่องหมายว่าช่วง 1 มกราคม~ก่อนลี่ชุน ดวงรายปีของปีก่อนยังดำเนินอยู่ ดวงรายปีคือก้าน-กิ่งของลี่ชุนปีนั้น (R-SAJU-UN-016)birthBeforeIpchun:trueหากเกิดช่วง 1 มกราคม~ก่อนลี่ชุน ทำให้เสาปีของผังดวงเป็นก้าน-กิ่งของปีก่อน (ฟิลด์ระดับบนสุด)assumedLocation(ตั้งแต่saju-flow-5ฟิลด์ระดับบนสุด): ค่าเริ่มต้นที่ใช้คำนวณเมื่อไม่ได้ส่งตำแหน่ง ตอนนี้เหมือนปฏิทินหมื่นปีคือ{ "correction": "none" }(ไม่ปรับเวลาสุริยะจริง) หากค่าเริ่มต้นของปฏิทินหมื่นปีเปลี่ยนเป็นลองจิจูดตัวแทน จะได้{ "correction": "trueSolarTime", "longitude": … }หากส่งตำแหน่ง (birthLatitude·birthLongitudeหรือcountry) จะเป็นnullnatalAmbiguous: หากไม่ทราบเวลาแต่วันเกิดมีจุดเปลี่ยนฤดู จะเป็น{ "pillar": "month" | "year", "termAt" }— เอนจินตัดสินตามเที่ยงวัน จึงเป็นเครื่องหมายว่าเสาเดือน (หากเป็นลี่ชุนรวมถึงเสาปี) อาจต่างจากความจริงcompatInputs: ค่าที่ให้แอปทำเพียงหาส่วนร่วมของเซตเมื่อดูหลายคนซ้อนกัน (ธาตุของธาตุช่วย จำนวนธาตุของอักษรที่ปรากฏ ธาตุที่ไม่ปรากฏ) ไม่สร้างผลรวม · อันดับระหว่างบุคคล
ราคา
- หากปิดการขายอยู่ จะคืน 404
saju_flow_not_enabled(ไม่คิดค่าบริการ) - หักเฉพาะเมื่อคำนวณสำเร็จ อินพุตผิดพลาด (400 — วันที่ไม่มีอยู่จริง ช่วงเกิน 101 ปี ฯลฯ) และ 409 ไม่คิดค่าบริการ
costPointsในการตอบกลับคือยอดที่หักครั้งนี้ (₩) endpoint ในบันทึกการใช้งานคือsaju-flow
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | saju_flow_not_enabled | บัญชียังไม่ได้เปิดฟีเจอร์ |
| 400 | INVALID_DATE | รูปแบบ birthDate ผิดพลาดหรือวันที่ไม่มีอยู่จริง |
| 400 | INVALID_LUNAR_DATE | วันที่จันทรคติที่ไม่มีอยู่จริง |
| 400 | INVALID_RANGE | toYear มาก่อน fromYear หรือเกิน 101 ปี |
| 400 | INVALID_TIME | birthTime ไม่ใช่รูปแบบ HH:mm |
| 400 | INVALID_LOCATION | ส่ง birthLatitude · birthLongitude เพียงค่าเดียว |
| 409 | saju_flow_correction_unsupported | ส่งตำแหน่งมาแต่เป็นการเกิดที่พบได้ยากซึ่งไม่สามารถย้ายผังดวง · เลขวัยจรที่ปรับแล้วมายังกราฟดวงชะตาให้เหมือนปฏิทินหมื่นปีได้ (วัดจริงประมาณ 0.1% — กรณีการปรับข้ามเที่ยงคืนทำให้เลขวัยจรเปลี่ยน กรณีไม่ทราบเวลาแต่การปรับเที่ยงวันข้ามจุดเปลี่ยนฤดู ฯลฯ) จะปฏิเสธโดยไม่แต่งค่าอื่นขึ้นมา (ไม่คิดค่าบริการ) การเกิดลักษณะนี้ให้ใช้ API ปฏิทินหมื่นปีด้วยตำแหน่งเดียวกัน |
| 402 | (ไม่มี) | ยอดคงเหลือน้อยกว่าค่าเรียก — API นี้ไม่ตรวจยอดคงเหลือก่อนเรียก จึงได้ 402 ที่ไม่มีรหัส |
API ดวงสมพงษ์
คำนวณดวงสมพงษ์จากซาจูของสองคน คืนดวงสมพงษ์ซาจู (ตารางดวงสมพงษ์เสาวัน 60×60 · คะแนนตามวัตถุประสงค์และ 6 แกน · ความสัมพันธ์ก้านฟ้า/กิ่งดิน · การเติมธาตุทั้งห้าของ 8 อักษร · สิบเทพ · ดาวพิเศษไขว้) ตารางสัญลักษณ์ความเข้ากันลึก (สัญลักษณ์ · ระดับจากตารางเสาวันชาย-หญิงของเอกสารอ้างอิง (1995)) ดวงสมพงษ์ราศี (3 ชั้น ดวงอาทิตย์ · ดวงจันทร์ · ลัคนา + ดาวตามวัตถุประสงค์ ย่อหน้าดวงสมพงษ์ราศีสูงสุด 2 ย่อหน้า) และดวงสมพงษ์ปีนักษัตร (ความสัมพันธ์กิ่งดินของปีนักษัตรทั้งสองและระดับ) ในครั้งเดียว พร้อมคะแนนรวม (headerBreakdown) ที่รวมคะแนนทั้งห้าด้วยน้ำหนักตามวัตถุประสงค์ ตั้งแต่ 2026-10-16 ยังมีตารางความสัมพันธ์ (relations) ที่รวบรวมการรวม · ปะทะ · ลงโทษ · ทำร้าย · ทำลาย ฯลฯ ระหว่างผังดวงทั้งสองแยกตามตำแหน่ง และคะแนนของตาราง (p2Score) มาด้วย เป็นเอนจินเดียวกับหน้าจอดวงสมพงษ์ของแอป INTA และอินพุตเดียวกันให้ผลเดียวกันเสมอ
คะแนนหลัก (ตัวเลขใหญ่) บนหน้าจอแอป INTA = headerBreakdown.average (62 ในตัวอย่างการตอบกลับด้านล่าง) saju.score.total (59 ในตัวอย่าง) เป็นคะแนนเฉพาะของ HRUM ที่เฉลี่ยเพียงตารางเสาวัน · 8 อักษร จึงต่างจากตัวเลขบนหน้าจอ
ค่าที่ตรงกับกราฟ 6 แกนบนหน้าจอผลลัพธ์ของแอป INTA คือ saju.iljuAxes (saju.axes เป็นค่าอื่นที่คำนวณใหม่ตามวัตถุประสงค์) ผู้ที่ทราบเวลาเกิดต้องส่ง personXCountry + personXBirthTimePrecision: "exact" ด้วยกันเหมือนการเรียกที่แนะนำ จึงจะคำนวณด้วยซาจูเดียวกับแอป INTA (ปรับเวลาสุริยะจริง)
POST /api/v1/partners/v1/compat
วิเคราะห์ดวงสมพงษ์จากซาจูของสองคน
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
personABirthDate |
string | O | วันเกิดของ A (YYYY-MM-DD ค่าเริ่มต้นสุริยคติ หาก personACalendar: "lunar" เป็นจันทรคติ) |
personABirthTime |
string | เวลาเกิดของ A (HH:MM ไม่บังคับ) | |
personAGender |
string | เพศของ A ("male"/"female" รับ "남"/"여" (ชาย/หญิง) ด้วย ไม่บังคับ) | |
personBBirthDate |
string | O | วันเกิดของ B (YYYY-MM-DD ค่าเริ่มต้นสุริยคติ หาก personBCalendar: "lunar" เป็นจันทรคติ) |
personBBirthTime |
string | เวลาเกิดของ B (HH:MM ไม่บังคับ) | |
personBGender |
string | เพศของ B ("male"/"female" รับ "남"/"여" (ชาย/หญิง) ด้วย ไม่บังคับ) | |
purpose |
string | วัตถุประสงค์ของดวงสมพงษ์ — yeonae_attraction (ความรัก ค่าเริ่มต้น) · marriage_stability (แต่งงาน) · friendship (มิตรภาพ) · family_bond (ครอบครัว) · coworker_cooperation (เพื่อนร่วมงาน) · business_partnership (ธุรกิจ) คะแนน · 6 แกน · ประเภทความสัมพันธ์ · คำบรรยายความสัมพันธ์ · ดาวที่ให้ความสำคัญในราศี · น้ำหนักคะแนนรวมจะเปลี่ยนไปตามวัตถุประสงค์ ค่าอื่นได้ 400 INVALID_PURPOSE (ไม่คิดค่าบริการ) |
|
lang |
string | ภาษาของประโยค — ko (ค่าเริ่มต้น) · en · ja · th ข้อความ categoryNarrative · astroReadings · astroSynastry · ระดับ classic1995 · tti จะมาเป็นภาษานี้ ในบล็อก saju ส่วน key · meetingKeywords · authority · full8 · conflict ของ relationRatings และ dayFlow.summary · yearFlow.years[].summary · dictionary ก็ตามภาษานี้ ตั้งแต่ 2026-10-13 ฟิลด์พื้นฐานของ saju (highlights · relation · tenGods · elements · bestFor/weakFor · pattern.name) ก็มาเป็นภาษานี้ด้วย mbti · yearFlow.years[].a/b ปัจจุบันมีเฉพาะภาษาเกาหลี |
|
personABirthTimePrecision / personBBirthTimePrecision |
string | ความแม่นยำของเวลา — exact · approximate (ระดับชั่วโมง) · estimated · unknown ดวงสมพงษ์ราศี: ค่าเริ่มต้นคือ exact หากมีเวลา ไม่มีคือ unknown ซาจู: การปรับเวลาสุริยะจริงใช้เฉพาะเมื่อเป็น exact หากละไว้แต่ส่งพิกัดหรือ personXCountry จะถือเป็น exact (กฎเดียวกับ API ปฏิทินหมื่นปี) |
|
personABirthLatitude / personABirthLongitudepersonBBirthLatitude / personBBirthLongitude |
number | พิกัดสถานที่เกิด (ส่งทั้งสองค่าพร้อมกัน) ใช้ทั้งในการคำนวณลัคนาและการปรับเวลาสุริยะจริงของซาจู (ใช้กับซาจูด้วยตั้งแต่ 2026-10-11) หากไม่มี ลัคนาจะประมาณจาก personXCountry และหากไม่มีอีกจะใช้พิกัดตัวแทนของประเทศตาม lang (ko→เกาหลี, ja→ญี่ปุ่น, th→ไทย / en ไม่แสดงลัคนา) |
|
personABirthTimezoneOffset / personBBirthTimezoneOffset |
number | ค่าชดเชย UTC (นาที) ค่าเริ่มต้น 540 (KST) หากส่งพร้อมพิกัด เส้นเมริเดียนมาตรฐานของการปรับซาจูก็กำหนดด้วยค่านี้ (หากละไว้ใช้เขตเวลาที่ใกล้ลองจิจูดที่สุด) หากส่ง personXBirthTimezone มาด้วย ฝั่งนั้นมีลำดับความสำคัญสูงกว่า |
|
personABirthTimezone / personBBirthTimezone |
string | เขตเวลาของสถานที่เกิด (IANA เช่น "America/New_York" ไม่บังคับ 2026-10-14) คำนวณซาจูด้วยกฎเดียวกับ timezone ของ API ปฏิทินหมื่นปี ข้อมูลการเกิดเดียวกันจึงได้สี่เสาเหมือน API ปฏิทินหมื่นปี — หากไม่ใช่โซล จะอ่านเวลาจุดเปลี่ยนฤดูด้วยเขตเวลานั้น (รวมเวลาออมแสง) และหากส่งพร้อมพิกัด จะใช้ค่าชดเชยมาตรฐานที่ไม่รวมเวลาออมแสงเป็นเกณฑ์การปรับ มีลำดับความสำคัญเหนือ personXBirthTimezoneOffset และผังดวงสมพงษ์ราศีจะวาดด้วยเวลาที่ใช้จริงในเขตเวลานี้ ณ เวลาเกิด (รวมเวลาออมแสง) หากละไว้จะคำนวณเหมือนเดิมทุกอย่าง (อ่านเวลาเกิดเป็นเวลาเกาหลี) หากเป็นชื่อที่ไม่รู้จัก จะคำนวณเหมือนกรณีละไว้ และการตอบกลับจะมี warnings (UNKNOWN_TIMEZONE คนละหนึ่งรายการ) แนบมา |
|
personACalendar · personAIsLeapMonthpersonBCalendar · personBIsLeapMonth |
string · boolean | หากเป็น "lunar" จะรับวันเกิดเป็นจันทรคติแล้วแปลงเป็นสุริยคติเพื่อคำนวณ (ค่าเริ่มต้น "solar") IsLeapMonth: true คือเดือนอธิกมาส หากปีนั้นไม่มีเดือนอธิกมาสนั้นหรือเป็นวันที่จันทรคติที่ไม่มีอยู่จริง จะได้ 400 INVALID_LUNAR_DATE (ไม่คิดค่าบริการ) หากมีผู้ที่ส่งเป็นจันทรคติ การตอบกลับจะมี lunarInput ({a, b} รูปแบบเดียวกับ API ปฏิทินหมื่นปี) แนบมา |
|
personACountry / personBCountry |
string | รหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับเวลาซาจูด้วยลองจิจูดตัวแทนของประเทศนั้น (ประเทศอื่นไม่มีการปรับ) การประมาณลัคนาของดวงสมพงษ์ราศีก็ใช้ประเทศนี้แทน lang |
|
personAZaSiRule / personBZaSiRule |
string | เสาวันของยามจื่อ (หลัง 23 นาฬิกา): "traditional" (ค่าเริ่มต้น เสาวันของวันถัดไป) · "yajaSi" (ยามจื่อกลางคืน เสาวันของวันนั้น · หลังปรับตามตำแหน่ง ก้านฟ้าของเสายามช่วง 23 นาฬิกาอิงก้านวันเกิดของวันถัดไป ตั้งแต่ 2026-10-20) |
|
details |
boolean | ค่าเริ่มต้น false หากเป็น true จะแนบ saju.full8 (การวิเคราะห์ 8 อักษรโดยละเอียด) · saju.conflict ({pattern, tip} รูปแบบความขัดแย้งและคำแนะนำ) · saju.relationScores (คะแนนความสัมพันธ์ก้านฟ้า · กิ่งดิน) · dictionary ระดับบนสุด ({a, b} พจนานุกรมเสาวันของสองคน — ค่าพื้นฐานของก้าน-กิ่ง (ธาตุทั้งห้า · หยิน-หยาง · ก้านแฝง · 12 วัฏจักรชีวิต) · คีย์เวิร์ดลักษณะนิสัย · สรุปหนึ่งบรรทัด) id (ilju_경진) · name_kr ของ dictionary.a/b เป็นค่ารหัสเสาวันที่ไม่ขึ้นกับภาษา (ภาษาเกาหลี) อักษรก้าน-กิ่งเดี่ยว · 12 วัฏจักรชีวิต ฯลฯ ของ en · th เป็นอักษรโรมัน (Gap · Mogyok) ส่วน ja เป็นอักษรจีน คีย์อ็อบเจกต์ personA/B.elementDistribution · sipsinCount · combinedElementBalance.distribution ของ saju.full8 เป็นค่ารหัสภาษาเกาหลีที่ไม่ขึ้นกับภาษา (목 · 비견 ฯลฯ) รายการทั้งหมดดูที่ ค่าที่ใช้ได้ > ค่ารหัสที่ไม่ขึ้นกับภาษา |
|
flow |
boolean | ค่าเริ่มต้น false หากเป็น true จะแนบ yearFlow (ปีอ้างอิง ±2 ปี กระแสของสองคนใน 5 ปี) และ dayFlow (วันอ้างอิง ±7 วัน กระแสของสองคนใน 15 วัน) |
|
date |
string | วันอ้างอิงของ flow YYYY-MM-DD (1900-2100) ค่าเริ่มต้น: วันนี้ตามเวลาเกาหลี |
|
currentYear |
number | ปีอ้างอิงของ yearFlow (1900~2100) ค่าเริ่มต้น: ปีของ date |
|
personAMbti / personBMbti |
string | MBTI 4 ตัวอักษร (เช่น ENFP ไม่สนตัวพิมพ์เล็ก-ใหญ่) หากส่งทั้งสองคน จะแนบ mbti ระดับบนสุด (ดวงสมพงษ์ MBTI ภาษาเกาหลี) |
ตัวเลือก details · flow · MBTI ไม่มีค่าบริการเพิ่ม (ยังเป็น ₩20 ต่อครั้งเหมือนเดิม)
- การปรับเวลา: ซาจูของแต่ละคน (เสาวัน · คะแนน 8 อักษร · คะแนนรวม · ตารางสัญลักษณ์ความเข้ากันลึก · ปีนักษัตร · การวิเคราะห์ตามผู้เชี่ยวชาญ ·
yearFlow· คำบรรยายความสัมพันธ์) จะคำนวณครั้งเดียวแล้วใช้ร่วมกันทุกรายการ หากไม่ส่งพิกัด ·personXCountry· ความแม่นยำexactจะคำนวณตามเวลาที่ป้อนเลย (เหมือน API ปฏิทินหมื่นปี) หากต้องการดวงสมพงษ์เดียวกับแอป INTA (ภาษาเกาหลี ป้อนเวลาเอง) ให้ส่งpersonXCountry: "KR"(+personXBirthTimePrecision: "exact") ทั้งสองคน — ดูการเรียกที่แนะนำด้านล่าง ผู้ที่ไม่มีเวลาเกิดจะไม่ถูกปรับ ค่าเริ่มต้น (ไม่ส่งก็ไม่ปรับ) ไม่เปลี่ยนแปลง - เปลี่ยนแปลง 2026-10-11: หากส่งพิกัด ซาจูก็จะปรับเวลาสุริยะจริงด้วย (ก่อนหน้านี้ใช้เฉพาะกับดวงสมพงษ์ราศี) เป็นการแก้ไขให้ซาจูและราศีในการตอบกลับเดียวกันใช้เกณฑ์เวลาเดียวกัน การเรียกที่เคยส่งพิกัดจึงอาจได้คะแนนซาจู · เสาวันที่เปลี่ยนไป ส่วนการตอบกลับของการเรียกที่ไม่ได้ส่งฟิลด์ใหม่และพิกัดยังเหมือนเดิม
- เสาวันเป็นค่ารหัส: ค่าของ
saju.personA.ilju·saju.personB.ilju(계미ฯลฯ) จะส่งเป็นค่ารหัสก้าน-กิ่งภาษาเกาหลีไม่ว่าlangจะเป็นอะไร ชื่อที่จะแสดงบนหน้าจอให้แปลงด้วยอภิธานศัพท์ (glossary) ของ API ปฏิทินหมื่นปี หรือการเขียนด้วยฮันจา (癸未สำหรับภาษาอังกฤษ · ภาษาไทยคือ癸未 (Gye-mi))
การเรียกที่แนะนำ (ผลเดียวกับแอป INTA)
สำหรับผู้ที่ทราบเวลาเกิด ให้ส่งประเทศเกิดและ "exact" มาด้วยกัน การปรับเวลาสุริยะจริงจะเหมือนแอป INTA แม้ผู้ที่เวลาเกิดอยู่ใกล้เส้นแบ่งยามก็จะได้เสาวัน · คะแนนเหมือนในแอป
{
"personABirthDate": "1990-09-04", "personABirthTime": "14:30", "personAGender": "male",
"personACountry": "KR", "personABirthTimePrecision": "exact",
"personBBirthDate": "1992-02-20", "personBBirthTime": "10:15", "personBGender": "female",
"personBCountry": "KR", "personBBirthTimePrecision": "exact",
"purpose": "yeonae_attraction", "details": true
}
ตัวอย่างการตอบกลับ
ด้านล่างคือผลลัพธ์จริงของเอนจิน (A ชาย 1990-09-04 14:30, B หญิง 1992-02-20 10:15 ความรัก ไม่มีพิกัด) ฟิลด์ที่รวมเสมอซึ่งเพิ่มเมื่อ 2026-10-10 (saju.relationRatings · saju.meetingKeywords · saju.authority · tti.conflictFrame) ถูกละไว้ในตัวอย่างนี้ — ดูตัวอย่างตัวเลือกด้านล่าง สองคนนี้แม้ส่งด้วยการเรียกที่แนะนำ (KR + exact) ก็ได้ค่าเดียวกัน
{
"success": true,
"data": {
"personABirthDate": "1990-09-04", "personABirthTime": "14:30", "personAGender": "male",
"personBBirthDate": "1992-02-20", "personBBirthTime": "10:15", "personBGender": "female",
"tti": {
"userTti": "말", "partnerTti": "원숭이",
"relation": { "type": null, "detail": null, "relations": [] },
"tier": "흉"
},
"saju": {
"purpose": "yeonae_attraction",
"hourKnown": { "a": true, "b": true },
"personA": { "ilju": "임신" },
"personB": { "ilju": "병인" },
"score": { "total": 59, "grade": "맞춰 가면 좋아요",
"breakdown": { "ilju": 53, "authority": 65, "eightChar": 65 } },
"axes": { "attraction": 25, "stability": 59, "growth": 58,
"communication": 24, "passion": 74, "longevity": 65 },
"pattern": { "name": "폭발형",
"description": "에너지가 크게 부딪히는 뜨거운 관계예요. 감정이 커질 때 잠시 쉬어 가는 규칙이 도움이 돼요." },
"relation": { "summary": "천간충 + 인신충",
"stem": { "type": "천간충", "detail": "병임충" },
"branches": [ { "type": "지지충", "detail": "인신충" } ] },
"elements": { "basis": "eight", "aLacks": [], "bProvidesToA": [], "bLacks": ["토"], "aProvidesToB": ["토"] },
"tenGods": { "aView": "편재", "bView": "편관(칠살)" },
"bestFor": ["단기 끌림"],
"weakFor": ["결혼·동거"],
"highlights": [ "상대의 시지에 나의 천을귀인 (사) 발현 — 상대가 나의 해결사" ],
"iljuAxes": { "attraction": 45, "stability": 16, "growth": 88,
"communication": 60, "passion": 70, "longevity": 50 }
},
"categoryNarrative": {
"category": "romantic", "purpose": "yeonae_attraction", "lang": "ko",
"text": "상대 쪽의 즉각적인 열정과 나 쪽의 자유로운 흐름은 불과 물처럼 정면으로 맞부딪혀서, 처음 만났을 때의 팽팽한 긴장감이 곧 끌림이 되기 쉬워요. 짧고 뜨거운 설렘이 큰 관계라, 감정이 치솟는 날엔 하루쯤 식힐 틈을 두면 더 즐겁게 만날 수 있어요.",
"styleVersion": "v2"
},
"costPoints": 20,
"classic1995": {
"symbol": "××", "grade": "대흉", "score": 50,
"ttiRelation": { "type": null, "detail": null, "relations": [] },
"conflictFrame": false
},
"relations": [
{ "positions": ["month", "month"], "kind": "chung", "tier": "heavyClash",
"ruleIds": ["R-SAJU-REL-034", "R-SAJU-COMPAT-106", "R-SAJU-COMPAT-112"], "chars": ["申", "寅"] },
{ "positions": ["day", "day"], "kind": "chung", "tier": "heavyClash",
"ruleIds": ["R-SAJU-REL-034", "R-SAJU-COMPAT-106", "R-SAJU-COMPAT-112"], "chars": ["申", "寅"] },
{ "positions": ["day", "day"], "kind": "stemChung", "tier": "clash",
"ruleIds": ["R-SAJU-REL-008", "R-SAJU-COMPAT-110"], "chars": ["壬", "丙"] },
{ "positions": ["year", "year"], "kind": "napeumSaeng", "tier": "gather",
"ruleIds": ["R-SAJU-BASE-037", "R-SAJU-COMPAT-111"], "chars": ["庚午", "壬申"] },
{ "positions": ["chart", "chart"], "kind": "banghap", "tier": "gather",
"ruleIds": ["R-SAJU-REL-021", "R-SAJU-COMPAT-104"], "chars": ["巳", "午", "未"] }
],
"p2Score": 57,
"astroSynastry": {
"self": {
"sun": { "signEn": "Virgo", "element": "earth", "modality": "mutable" },
"moon": { "signEn": "Pisces", "element": "water", "modality": "mutable", "uncertain": false },
"ascendant": { "signEn": "Sagittarius", "element": "fire", "modality": "mutable", "uncertain": false, "countryBasis": true },
"venus": { "signEn": "Leo", ... }, "mars": { "signEn": "Gemini", ... },
"mercury": { ... }, "jupiter": { ... }, "saturn": { ... }
},
"partner": { "sun": { "signEn": "Pisces", ... }, "moon": { "signEn": "Virgo", ... }, ... },
"layers": [
{ "key": "sun", "relation": "opposite", "selfSign": "Virgo", "partnerSign": "Pisces",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "key": "moon", "relation": "opposite", "selfSign": "Pisces", "partnerSign": "Virgo",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "key": "ascendant", "relation": "neutral", "selfSign": "Sagittarius", "partnerSign": "Taurus",
"textKey": "compat.astro.relation.neutral",
"text": "뚜렷한 결 없이 각자의 스타일을 존중하면 되는 조합이에요" }
],
"purposeBodies": [
{ "body": "venus", "relation": "opposite", "selfSign": "Leo", "partnerSign": "Aquarius",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "body": "mars", "relation": "same_element", "selfSign": "Gemini", "partnerSign": "Aquarius",
"textKey": "compat.astro.relation.same_element",
"text": "같은 원소 — 서로의 방식을 바로 알아볼 만큼 편안할 수 있어요" }
],
"caveats": ["compat.astro.caveat.ascendantCountryBasis"],
"caveatTexts": ["상승궁은 출생 도시가 없어 국가 대표 좌표로 추정했어요"],
"score": 64
},
"astroReadings": [
{ "key": "Su_Mo_ss", "lang": "ko",
"text": "한쪽의 태양과 다른 쪽의 달이 같은 별자리에 놓이면, 한 사람이 향하는 방향을 다른 사람의 마음이 낯설지 않게 알아보는 깊은 공명이 생기기 쉬워요. 닮은 만큼 같은 그림자도 함께 커질 수 있으니 서로의 빈틈을 웃으며 짚어 주면 좋아요." },
{ "key": "Ve_Ma_op", "lang": "ko",
"text": "한쪽의 금성과 다른 쪽의 화성이 정반대 별자리에 놓이면, 서로에게 없는 매력을 알아보며 끌리는 보완의 흐름이 생기기 쉬워요. 원하는 속도와 표현 방식이 반대로 기울 수 있으니 서로의 선을 말로 정해 두면 그 끌림이 편안하게 이어져요." }
],
"headerBreakdown": {
"sixAxis": 55, "authority": 65, "full8": 65, "classic": 57, "natal": 64,
"average": 62, "purpose": "yeonae_attraction",
"weights": { "sixAxis": 0.2, "authority": 0.3, "full8": 0.2, "classic": 0.1, "natal": 0.2 }
},
"engineVersion": "compat-2",
"lang": "ko"
}
}
saju(ดวงสมพงษ์ซาจู) เป็นส่วนหลัก ในกรณีที่พบได้ยากซึ่งคำนวณเสาวันไม่ได้จะเป็นnull— ในกรณีนั้นให้แสดงเฉพาะttisaju.score.total: 0~100 ค่าเฉลี่ยของคะแนนตารางดวงสมพงษ์เสาวันและคะแนนการวิเคราะห์ 8 อักษร (แต่ละค่าอยู่ในbreakdown)gradeคือระดับเป็นคำง่ายๆ — 아주 잘 맞아요 (เข้ากันดีมาก 85 ขึ้นไป) · 잘 맞아요 (เข้ากันดี 75 ขึ้นไป) · 무난해요 (พอไปได้ 65 ขึ้นไป) · 맞춰 가면 좋아요 (ปรับเข้าหากันจะดี 55 ขึ้นไป) · 서로 많이 달라요 (ต่างกันมาก) ค่านี้เหมือนเดิม — คะแนนที่รวมถึงตารางสัญลักษณ์ · ราศีคือheaderBreakdown.averagesaju.axes: 6 แกน แรงดึงดูด · ความมั่นคง · การเติบโต · การสื่อสาร · ความหลงใหล · ความยั่งยืน (0~100) เปลี่ยนไปตามpurposesaju.pattern: ชื่อและคำอธิบายประเภทความสัมพันธ์ (หากไม่มีเป็นnull)saju.iljuAxes(ตั้งแต่ 2026-10-27): ค่าเดียวกับกราฟ 6 แกนบนหน้าจอผลลัพธ์ของแอป INTA — 6 แกนจากตารางดวงสมพงษ์ของคู่เสาวันสองคนตามเดิม (attraction·stability·growth·communication·passion·longevity0~100 ไม่ขึ้นกับpurpose) ค่าเฉลี่ย 6 แกนคือheaderBreakdown.sixAxisคีย์เหมือนsaju.axesแต่การคำนวณต่างกันจึงได้ตัวเลขต่างกัน หากตารางดวงสมพงษ์ไม่มีคู่นั้นจะเป็นnullsaju.elements: คำนวณจากการกระจายธาตุทั้งห้าของผังดวงทั้งหมดของสองคน (หากไม่ทราบเวลาใช้ 6 อักษร —basis: "six")bProvidesToA= ธาตุที่ A ไม่มีแต่ B มีsaju.tenGods: สิบเทพของ B เมื่อมองจาก A (aView) และในทางกลับกัน (bView)highlights: ประโยคดาวพิเศษไขว้ที่พบใน 8 อักษร (สูงสุด 5 รายการ หากไม่มีเป็นอาร์เรย์ว่าง)relations(ตั้งแต่ 2026-10-16): รายการความสัมพันธ์ระหว่างผังดวงทั้งสอง ดูคู่กิ่งดินตำแหน่งเดียวกัน (ปี · เดือน · วัน · ยาม — เสายามเฉพาะเมื่อทั้งสองคนมีเวลาเกิด) การรวม · ปะทะของก้านฟ้าระหว่างก้านวันเกิดของทั้งสอง ธาตุนาบึมของเสาปี และรวมสาม · รวมทิศที่เกิดขึ้นได้เมื่อรวมผังดวงทั้งสอง แต่ละรายการมีpositions([ฝั่ง A, ฝั่ง B]—year·month·day·hourรวมสาม · รวมทิศคือchart= ผังดวงทั้งหมด)kind(ตารางด้านล่าง)tierruleIds(ID กฎ KB ที่เป็นหลักฐาน — ตรวจแหล่งที่มาต้นฉบับได้ใน KB API)chars(อักษรของความสัมพันธ์ เป็นฮันจา) ทุกคีย์ไม่ขึ้นกับภาษา แม้เปลี่ยนlangก็เหมือนเดิม ข้อความบนหน้าจอให้สร้างเองจากkindไม่มีคำตัดสินว่าดีหรือไม่ดี หากตั้งผังดวงไม่ได้เป็นnullหากไม่มีความสัมพันธ์เลยเป็นอาร์เรย์ว่างtier:gatherการรวมตัว (ฝั่งการรวม) ·clashการขัดกัน ·heavyClashการขัดกันรุนแรง (ความสัมพันธ์ที่ตำราจัดลำดับว่าหนักกว่า ตอนนี้คือการปะทะ) ·listOnlyแสดงในรายการเท่านั้น (ความสัมพันธ์ที่ไม่พบหลักฐานทิศทางในตำรา จึงไม่นำมาคิดคะแนน)p2Score(ตั้งแต่ 2026-10-16): 0~100 ค่าที่ตัดround(71.6 + 5 × Σ)ให้อยู่ใน 0~100 — Σ = ผลรวมของแต่ละความสัมพันธ์gather+1 ·clash−1 ·heavyClash−2 ·listOnly0 1 หน่วย = 5 คะแนน และ 71.6 คือจุดกลางเมื่อไม่มีความสัมพันธ์เลย (ค่าเฉลี่ยจากสมาชิกจริงของคะแนนแกนตำราเดิม ณ 2026-10-16) ใช้มาตราเดียวกันไม่ว่าจะมีเสายามหรือไม่ ตำราบอกเพียงทิศทางและลำดับของความสัมพันธ์ ไม่ได้บอกขนาด — ตัวเลขนี้เป็นมาตราสมมติสำหรับแสดงบนหน้าจอ ไม่ใช่คะแนนจากตำรา (KBR-SAJU-COMPAT-113) หากrelationsเป็นnullจะเป็นnullclassic1995(กำหนดยุติการรองรับ): ตอนนี้ยังมาเหมือนเดิมทุกอย่าง กำหนดการยุติ (ร่าง): ประกาศ 2026-11-16 → คงไว้ถึง 2026-12-31 → ตั้งแต่ 2027-01-01 เป็นnullวันที่อาจเปลี่ยนตามประกาศการให้บริการ หากเชื่อมต่อใหม่ให้ใช้relations·p2Scoreสัญลักษณ์ในตารางความเข้ากันลึกเสาวันชาย-หญิงของเอกสารอ้างอิง (1995) (●대길 (ดีมาก) 100 ·◎중길 (ดีปานกลาง) 90 ·○길 (ดี) 80 ·△무해무덕 (ไม่ดีไม่ร้าย) 70 ·×흉 (ร้าย) 60 ·××대흉 (ร้ายมาก) 50) ตารางนี้เป็นตารางทิศทางเสาวันชาย × เสาวันหญิง หากเป็นเพศเดียวกันหรือไม่ส่งเพศ จะอ่านทั้งสองทิศทาง (A เป็นชาย · B เป็นชาย)scoreคือค่าเฉลี่ยของสองคะแนน (เช่น 95) และsymbol·gradeคือระดับที่ปัดค่าเฉลี่ยนั้นลงทีละ 10 คะแนน (เช่น 95 →◎중길) หากสองทิศทางเหมือนกันจะใช้สัญลักษณ์นั้นตามเดิมconflictFrame: เป็นtrueเมื่อสัญลักษณ์ดีแต่ความสัมพันธ์ปีนักษัตรร้าย หรือกลับกัน หากหาเสาวันไม่ได้ทั้งหมดจะเป็นnullastroSynastry: ดวงสมพงษ์ราศีlayers= เปรียบเทียบ 3 ชั้น ดวงอาทิตย์ · ดวงจันทร์ · ลัคนาpurposeBodies= ดาวที่ให้ความสำคัญตามวัตถุประสงค์ (ความรัก: ดาวศุกร์ · ดาวอังคาร แต่งงาน: +ดาวเสาร์ มิตรภาพ: ดาวพุธ · ดาวพฤหัสบดี …)relation=same_sign·opposite·same_element·element_support·same_modality·element_friction·neutralและtextคือคำอธิบายความหมาย (lang)score0~100caveats/caveatTexts: ระบุหากลัคนา · ราศีจันทร์เป็นค่าประมาณ หากไม่ทราบเวลา ชั้นลัคนาจะถูกตัดออกastroReadings: ย่อหน้าการอ่านที่เขียนไว้ล่วงหน้าสำหรับจุดสัมผัสที่โดดเด่นที่สุดในราศีของสองคน (ดวงอาทิตย์–ดวงจันทร์ ดาวศุกร์–ดาวอังคาร ฯลฯ) สูงสุด 2 รายการ หากไม่มีเป็นอาร์เรย์ว่างlangของแต่ละย่อหน้าคือภาษาจริงของประโยค (หากไม่มีประโยคในภาษาที่ขอเป็นko)headerBreakdown: คะแนนรวมaverage(0~100) ที่รวมห้าคะแนน ได้แก่ ค่าเฉลี่ย 6 แกน · ผู้เชี่ยวชาญ (authority) · 8 อักษร (full8) · ส่วนของตำรา (classic— ตั้งแต่ 2026-10-16 คือp2Scoreก่อนหน้านั้นคือclassic1995.score) · ราศี (natal) ด้วยน้ำหนัก (weights) ตามpurposeคะแนนที่ขาดไปจะแบ่งน้ำหนักใหม่ให้ที่เหลือ เป็นค่าเดียวกับคะแนนหลัก (ตัวเลขใหญ่) บนหน้าจอดวงสมพงษ์ของแอป INTA (62 ในตัวอย่างข้างต้น) ตั้งแต่ 2026-10-16 น้ำหนักส่วนของตำรา (classic) สำหรับวัตถุประสงค์แต่งงาน (marriage_stability) ลดจาก 0.25 → 0.05 และส่วนที่ลดไป 0.20 ถูกแบ่งให้อีกสี่แกนตามสัดส่วนเดิม (sixAxis0.15 → 0.19 ·authority0.25 → 0.3167 ·full80.25 → 0.3167 ·natal0.10 → 0.1267) น้ำหนักของวัตถุประสงค์อื่นคงเดิม หากหาตารางดวงสมพงษ์เสาวันไม่ได้จะเป็นnull- ปีของวันเกิดต้องอยู่ระหว่าง 1900~2100 — หากเกินจะได้ 400
INVALID_BIRTH_YEAR(ไม่คิดค่าบริการ) หากพิมพ์ปีเป็นสองหลักในช่องป้อนวันที่จะกลายเป็นอย่าง0090ให้ป้องกันบนหน้าจอด้วย หากหาผลในตารางดวงสมพงษ์ไม่ได้จะได้ 400COMPAT_UNAVAILABLE(ไม่คิดค่าบริการ) tti.tier: สตริงระดับของดวงสมพงษ์ปีนักษัตรจากเอกสารอ้างอิง (1995) (เช่น 대길 · 길 · 중길 · 보통 · 주의 · 흉 — จากดีมากถึงร้าย)tti.relation.type= ความสัมพันธ์ของกิ่งดินปีนักษัตรทั้งสอง — หนึ่งใน충(ปะทะ) ·원진(ขุ่นเคือง) ·형(ลงโทษ) ·해(ทำร้าย) ·육합(รวมหก) ·반합(รวมครึ่ง) ·파(ทำลาย) (หากหลายความสัมพันธ์ซ้อนกัน ใช้ตัวที่มาก่อนตามลำดับนี้) หากไม่มีเป็นnulldetailมีเฉพาะเมื่อเป็นรวมครึ่ง (เช่น 수국(水局))tti.relation.relations= ความสัมพันธ์ที่ซ้อนกันทั้งหมด (ลำดับเดียวกัน เช่น ปีวัว · ปีแพะ["충","형"]หากไม่มีเป็นอาร์เรย์ว่าง)ttiมีเพียงปีนักษัตร · ความสัมพันธ์ · ระดับ ไม่ใส่ประโยคดวงสมพงษ์ปีนักษัตรจากเอกสารอ้างอิง (ตั้งแต่ 2026-10-11)categoryNarrative: 2~3 ประโยคที่บรรยายว่าสองคนเป็นอย่างไรในความสัมพันธ์นี้ (purpose) เป็นประโยคที่เขียนไว้ล่วงหน้าสำหรับคู่เสาวันของสองคน (1,830 คู่) และความสัมพันธ์ 6 ประเภท อินพุตเดียวกันจึงได้ประโยคเดิมเสมอ ในประโยค나= A,상대= B (ภาษาอังกฤษYou/Your partnerภาษาญี่ปุ่นあなた/相手ภาษาไทยคุณ/คู่ของคุณ) มี 4 ภาษาตามlangหากหาประโยคไม่ได้เป็นnull(คิดค่าบริการเท่าเดิม)- รวมเสมอ (ตั้งแต่ 2026-10-10):
saju.relationRatings={ key, stars }ของความสัมพันธ์ 5 ประเภท (ตัวอย่างkey: 연애 (ความรัก) · 결혼·동거 (แต่งงาน · อยู่ด้วยกัน) · 친구 (เพื่อน) · 사업 파트너 (หุ้นส่วนธุรกิจ) · 장기 관계 (ความสัมพันธ์ระยะยาว) / ดาว 1~5) ·saju.meetingKeywords= คีย์เวิร์ดการพบกัน 3 คำ ·saju.authority= การตัดสินดวงสมพงษ์ตามผู้เชี่ยวชาญ (finalScore·grade·gradeTier·pattern·summary·levels(L1~L4) ·factors·flags·climateBalance) ·tti.conflictFrame= ค่าเดียวกับclassic1995.conflictFrame yearFlow.years[].tier:great·good·neutral·cautiondayFlow.days[].tier:golden·good·neutral·dim·hard(dayFlow.golden/hardคือรายการวันที่ที่เกี่ยวข้อง)
ประเภทความสัมพันธ์ (relations[].kind)
kind | ความหมาย | tier |
|---|---|---|
yukhap | รวมหกของกิ่งดิน — กิ่งดินสองตัวจับคู่รวมกัน | gather |
banhap | รวมครึ่งของกิ่งดิน — สองในสามอักษรของรวมสาม | listOnly |
samhap | รวมสาม — รวมผังดวงทั้งสองแล้วอักษรสามตัวมารวมกันเป็นกลุ่มธาตุเดียว | gather |
banghap | รวมทิศ — รวมผังดวงทั้งสองแล้วกิ่งดินสามตัวของฤดูเดียวกันมารวมกัน | gather |
chung | ปะทะของกิ่งดิน — ชนกันตรงๆ | heavyClash |
hyung | ลงโทษของกิ่งดิน | clash |
hae | ทำร้ายของกิ่งดิน | clash |
pa | ทำลายของกิ่งดิน (คู่ 寅亥·巳申 เป็นรวมหกจึงเป็น listOnly) | clash |
wonjin | ขุ่นเคือง (wonjin) | listOnly |
stemHap | การรวมก้านฟ้าระหว่างก้านวันเกิด | gather |
stemChung | การปะทะก้านฟ้าระหว่างก้านวันเกิด | clash |
napeumSaeng | ธาตุนาบึมของเสาปีส่งเสริมกัน | gather |
napeumBihwa | ธาตุนาบึมของเสาปีเหมือนกัน | gather |
napeumGeuk | ธาตุนาบึมของเสาปีข่มกัน | clash |
kind เดียวกันมี tier เดียวกันเสมอ (ยกเว้นสองคู่ของการทำลาย) อาจมี kind ใหม่เกิดขึ้น จึงควรทำให้ข้ามค่าที่ไม่รู้จัก
ตัวอย่างตัวเลือก (details · flow · MBTI)
ตัดตอนผลลัพธ์จริงของเอนจิน คำขอ:
{
"personABirthDate": "1990-05-15", "personABirthTime": "12:00", "personAGender": "male",
"personBBirthDate": "1992-08-20", "personBBirthTime": "09:00", "personBGender": "female",
"details": true, "flow": true, "date": "2026-10-10",
"personAMbti": "ENFP", "personBMbti": "ISTJ"
}
{
"success": true,
"data": {
"tti": { "userTti": "말", "partnerTti": "원숭이", ..., "tier": "흉", "conflictFrame": false },
"saju": {
"personA": { "ilju": "경진" }, "personB": { "ilju": "무진" },
"score": { "total": 56, "grade": "맞춰 가면 좋아요", ... },
...,
"relationRatings": [
{ "key": "연애", "stars": 3 }, { "key": "결혼·동거", "stars": 3 }, { "key": "친구", "stars": 4 },
{ "key": "사업 파트너", "stars": 3 }, { "key": "장기 관계", "stars": 3 }
],
"meetingKeywords": ["괴강", "우직", "일반적 관계"],
"authority": {
"finalScore": 51, "grade": "주의", "gradeTier": "caution",
"pattern": "자형 (자기 갈등 외부화)",
"summary": "주의 · 자형 (자기 갈등 외부화) · 익숙한 결의 만남. 안락함 위에 자극을 어떻게 만들지가 핵심.",
"levels": { "L1": { "raw": 0, "norm": 0 }, "L2": { "raw": 5, "norm": 14.3, "type": "동계절 (봄)" },
"L3": { "raw": 17, "norm": 56.7 }, "L4": { "raw": -17, "norm": -42.5 } },
"factors": { "l1": [], "l2Tone": "...", "l3": [ ... ], "l4": ["자형(진진) — 자기 파괴 패턴", ...] },
"flags": { "cheonHapJiHap": false, "dualChung": false },
"climateBalance": "동계절 (봄)"
},
"conflict": {
"pattern": "경은 무를 편인으로 인식. 일방향적 관계 성격.",
"tip": "'괴강'과 '우직'은 서로 다른 결이에요. 같은 사건도 다르게 해석한다는 걸 인정하고, 서로의 관점을 한 번씩 빌려보세요."
},
"relationScores": { "stem": { "type": "편인", "category": "neutral", "score": 55 },
"branches": [ { "type": "자형", "score": -40 } ] },
"full8": { "personA": { ... }, "personB": { ... }, "iljuEvaluation": { ... }, ... }
},
...,
"dictionary": { "a": { "id": "ilju_경진", "name_kr": "경진", "name_hanja": "庚辰", ... }, "b": { ... } },
"yearFlow": {
"baseYear": 2026,
"years": [
{ "year": 2024, "score": 77, "tier": "great", "a": { ... }, "b": { ... },
"summary": "두 분 모두 흐름이 좋아 같이 시작하기 좋은 해." },
...
]
},
"dayFlow": {
"baseDate": "2026-10-10",
"days": [
{ "date": "2026-10-03", "a": -89, "b": -40, "combined": -60, "tier": "hard", "isBaseDate": false },
...,
{ "date": "2026-10-10", "a": -9, "b": 27, "combined": 9, "tier": "neutral", "isBaseDate": true },
...
],
"golden": [],
"hard": [ { "date": "2026-10-03", "combined": -60 }, ... ],
"summary": "3번 같이 가라앉는 날이 있어. 그날은 큰 결정·약속 미루자."
},
"mbti": { "id": "mbti_ENFP_ISTJ", "mbti_a": "ENFP", "mbti_b": "ISTJ",
"socionics_relation": "Duality(이중관계)", "scores": { ..., "total": 64 }, ... }
}
}
ข้อควรระวัง
- ข้อมูลพื้นฐาน: วันเกิดของทั้งสองคนเป็นข้อมูลจำเป็น เวลาและเพศไม่บังคับ แม้ไม่มีเพศหรือเพศเดียวกัน ตารางสัญลักษณ์ความเข้ากันลึกก็ยังออกมา (รวมสองทิศทาง) ส่วนลัคนาของดวงสมพงษ์ราศีต้องมีเวลาเกิดจึงจะออกมา
- โครงสร้างผลลัพธ์: ดวงสมพงษ์ราศีอิงจักรราศีแบบทรอปิคัล คำบรรยายตามความสัมพันธ์มาใน
categoryNarrativeและย่อหน้าราศีมาในastroReadingsด้วยกัน หากต้องการคำอ่านเฉพาะบุคคลที่ยาวกว่านี้ ให้นำผลลัพธ์ไปใส่ในคำถามของ/reading - เปลี่ยนแปลง 2026-10-16 (
engineVersioncompat-2): เพิ่มrelations·p2Score·engineVersionใหม่ และheaderBreakdown.classicเปลี่ยนเป็นp2Scoreทำให้headerBreakdown.averageอาจต่างจากเดิม (ค่าเดียวกับหน้าจอดวงสมพงษ์ของแอป INTA) ค่าของฟิลด์เดิมอื่นๆ คงเดิม - ความเข้ากันได้: ฟิลด์ที่เพิ่มในเดือน 2026-10 (
classic1995·astroSynastry·astroReadings·headerBreakdown·langและsaju.relationRatings·saju.meetingKeywords·saju.authority·tti.conflictFrameของ 2026-10-10) จะแนบมาเสมอไม่ว่าจะส่งlangหรือไม่ ค่าของฟิลด์เดิมคงเดิม แต่ตั้งแต่ 2026-10-11 ฟิลด์ที่ยกประโยคจากเอกสารอ้างอิง (1995) — คำอ่านหนึ่งบรรทัดของดวงสมพงษ์ปีนักษัตร และดวงความรัก · ดวงสุขภาพในพจนานุกรมเสาวัน — ถูกนำออกจากการตอบกลับแล้ว - เพิ่มเมื่อ 2026-10-27: เพิ่ม
saju.iljuAxesใหม่ (เสมอ ท้ายสุดของบล็อกsaju) ค่าและลำดับของฟิลด์เดิมคงเดิม และengineVersionก็ยังเป็นcompat-2 - เปลี่ยนแปลง 2026-10-31: แก้คำช่วยในประโยคภาษาเกาหลีของดวงสมพงษ์ให้ตรงกับตัวสะกดท้าย (เช่น “임와” → “임과”, “병는” → “병은”) คีย์ · ลำดับ · ตัวเลข และประโยคภาษาอื่นคงเดิม
- ค่าใช้จ่าย: หัก ₩20 ต่อการเรียก (รวมฟิลด์เพิ่มเติม · ตัวเลือก
details·flow· MBTI ไม่มีค่าบริการเพิ่ม)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | INVALID_BIRTH_YEAR | ปีเกิดของคนใดคนหนึ่งอยู่นอก 1900~2100 |
| 400 | INVALID_LUNAR_DATE | วันที่จันทรคติที่ไม่มีอยู่จริง |
| 400 | COMPAT_UNAVAILABLE | ไม่มีข้อมูลดวงสมพงษ์ของคู่เสาวันนี้ |
| 402 | INSUFFICIENT_BALANCE | ยอดคงเหลือไม่พอ |
ตัวอย่างคำขอดูได้ที่ตัวอย่างตัวเลือกข้างต้นและตัวอย่างการเรียกใช้
API ประเภทบุคลิกภาพ
ให้บริการแบบทดสอบบุคลิกภาพตาม MBTI รองรับเวอร์ชันไลต์ฟรี (24 ข้อ) และเวอร์ชันพรีเมียม (93 ข้อ)
GET /api/v1/partners/v1/personality-type/questions
ดึงข้อคำถามของแบบทดสอบบุคลิกภาพ ใช้ได้ฟรี
curl "https://api.hrum.ai/api/v1/partners/v1/personality-type/questions?tier=free" \
-H "X-Partner-Api-Key: your-api-key"
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
tier |
string | เวอร์ชันแบบทดสอบ ("free" หรือ "premium" ค่าเริ่มต้น: "free") |
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"tier": "free",
"count": 24,
"questions": [
{
"id": "q_001",
"text": "갑자기 생긴 모임에도 일단 가본다",
"choices": [
{ "value": 1, "label": "전혀 그렇지 않다" },
{ "value": 2, "label": "그렇지 않다" },
{ "value": 3, "label": "보통이다" },
{ "value": 4, "label": "그렇다" },
{ "value": 5, "label": "매우 그렇다" }
]
}
]
}
}
POST /api/v1/partners/v1/personality-type
ส่งคำตอบของแบบทดสอบบุคลิกภาพเพื่อวิเคราะห์ประเภทบุคลิกภาพ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/personality-type \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"tier": "free",
"answers": [
{ "questionId": "q_001", "answer": 4 },
{ "questionId": "q_002", "answer": 2 }
]
}'
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
answers |
array | O | อาร์เรย์คำตอบ [{ "questionId": "q_001", "answer": 4 }, ...] questionId คือ id ในการตอบกลับของการดึงข้อคำถาม (รูปแบบ q_001) answer คือจำนวนเต็ม 1~5 สำหรับ premium ต้องมีคำตอบอย่างน้อยหนึ่งข้อในทุกแกนทั้งสี่ (เปิดเผย · เก็บตัว / ประสาทสัมผัส · สัญชาตญาณ / ความคิด · ความรู้สึก / การตัดสิน · การรับรู้) (หากไม่มีจะได้ 400 personality_axis_unanswered) เพื่อผลลัพธ์ที่แม่นยำ แนะนำให้ตอบครบทั้ง 93 ข้อที่ได้จากการดึงข้อคำถาม |
tier |
string | O | "free" หรือ "premium" |
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"personalityType": "ENTJ",
"typeLabel": "지휘관",
"scores": {
"extraversion": 72,
"sensing": 45,
"thinking": 68,
"judging": 80
},
"tier": "premium",
"costPoints": 10
}
}
ราคา
- เวอร์ชันฟรี (free): 24 ข้อ ₩0 (ฟรี)
- พรีเมียม (premium): 93 ข้อ ₩10/ครั้ง
questionIdที่ไม่มีอยู่หรือanswerนอก 1~5 จะได้ 400 และไม่คิดค่าบริการ- ใน
premiumหากมีแกนที่ไม่มีคำตอบเลยจะได้ 400personality_axis_unansweredและไม่คิดค่าบริการaxesในการตอบกลับจะมีแกนที่ว่าง (E_I·S_N·T_F·J_P)
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 400 | (ไม่มี) | ดึงข้อคำถาม — tier ไม่ใช่ free · premium / ส่งคำตอบ — questionId ที่ไม่มีอยู่ |
| 400 | personality_axis_unanswered | ส่งคำตอบ — เป็น premium แต่มีแกนที่ไม่มีคำตอบเลย (แกนว่างอยู่ใน axes) |
| 402 | INSUFFICIENT_BALANCE | ส่งคำตอบ — เป็น premium แต่ยอดคงเหลือไม่พอ |
หากคำตอบอยู่นอก 1~5 จะได้ 400 ทั่วไป ทั้งหมดไม่คิดค่าบริการ
API ฐานข้อมูลการตีความ (KB)
API ที่เปิดเฉพาะบัญชีที่ยื่นขอ บัญชีที่ยังไม่เปิดจะได้ 404 kb_saju_explain_not_enabled ในทั้งสามเส้นทาง (ไม่คิดค่าบริการ) หากต้องการใช้ โปรดติดต่อฝ่ายสนับสนุน
อธิบายความสัมพันธ์ (การรวม · ปะทะ ฯลฯ) และโครงสร้าง (สิบเทพ · ก้านแฝง ฯลฯ) ที่เกิดขึ้นในผังดวงซาจูด้วยการ์ดกฎและประโยคคำอธิบาย ไม่ใช้ LLM อินพุตเดียวกันจึงได้ผลเดียวกันเสมอ
POST /api/v1/partners/v1/kb/saju/explain
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
birth | object | O | ฟิลด์เดียวกับเนื้อหาคำขอของ API ปฏิทินหมื่นปี (year · month · day · hour? · minute? · timezone · gender · calendar? …) birth.lang จะถูกละเว้น หากไม่รู้จัก birth.timezone การตอบกลับจะมี warnings (field: "birth.timezone") แนบมา |
sections | string[] | relations · structure · all หากละไว้คือทั้งหมด (ลำดับ relations → structure) | |
level | string | L1 (ค่าเริ่มต้น) · L3 รายการที่ไม่มีคำอธิบาย L3 จะเติมด้วย L1 และแนบ fallbackLevel | |
lang | string | รองรับเฉพาะ ko | |
channel | string | stable (ค่าเริ่มต้น เฉพาะคำอธิบายที่ตรวจทานแล้ว) · preview (รวมคำอธิบายที่ยังไม่ตรวจทาน — เฉพาะบัญชีที่ได้รับอนุญาตแยก นอกนั้นได้ 403 KB_PREVIEW_NOT_ALLOWED) |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/kb/saju/explain \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"birth": {
"year": 1990, "month": 5, "day": 17, "hour": 14, "minute": 30,
"timezone": "Asia/Seoul", "gender": "female"
},
"sections": ["relations"]
}'
ตัวอย่างการตอบกลับ (ตัดตอน)
{
"success": true,
"data": {
"kbVersion": "2026.10.09-3",
"kbHash": "sha256:24b9a2d9...",
"channel": "stable",
"chart": {
"pillars": {
"year": { "stem": "庚", "branch": "午" },
"month": { "stem": "辛", "branch": "巳" },
"day": { "stem": "壬", "branch": "午" },
"hour": { "stem": "丁", "branch": "未" }
},
"timeUnknown": false
},
"sections": [
{
"id": "relations",
"title": "...",
"steps": [
{
"fact": { "type": "stem_pair", "a": "壬", "b": "丁", "posA": "day", "posB": "hour", "relation": "hap" },
"factText": "일간 壬과 시간 丁은 천간합(天干合) 관계다.",
"componentId": "saju:stem_pair:丁壬:hap",
"rules": [
{ "id": "R-SAJU-REL-004", "kind": "definition", "status": "verified", "sourceCount": 2,
"statement": "丁과 壬은 천간합 관계이고, 이 짝의 합화 오행은 목(木)이다." }
],
"interp": {
"meaning": { "text": "丁(정)과 壬(임)은 천간합으로 묶이는 짝이고, ...", "reviewed": false },
"why": { ... },
"pitfall": { ... }
}
}
],
"absent": [
{ "type": "stem_pair", "a": "庚", "b": "辛", "posA": "year", "posB": "month",
"note": "庚과 辛은 천간합·천간충 어느 것도 아니다." }
]
}
],
"unregistered": [],
"pendingReview": []
}
}
interpคือช่องคำอธิบาย (meaningความหมาย ·whyเหตุผล ·pitfallข้อควรระวัง) แต่ละช่องเป็น{text, reviewed, reviewedBy?, notes?}และในstableจะออกเฉพาะช่องที่ตรวจทานแล้วunregistered: รายการที่เกิดขึ้นแต่ยังไม่มีคำอธิบายpendingReview: รายการที่มีคำอธิบายแต่ยังไม่ตรวจทาน จึงซ่อนไว้ในstable- แหล่งที่มาจากตำราของการ์ดกฎดึงได้ด้วย
GET /kb/rules/{id}ด้านล่าง
GET /api/v1/partners/v1/kb/rules/{id}
คืนการ์ดกฎหนึ่งใบพร้อมแหล่งที่มาจากตำรา ใช้ได้ฟรี
curl https://api.hrum.ai/api/v1/partners/v1/kb/rules/R-SAJU-REL-004 \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"id": "R-SAJU-REL-004",
"kind": "definition",
"statement": "丁과 壬은 천간합 관계이고, 이 짝의 합화 오행은 목(木)이다.",
"status": "verified",
"schools": [],
"variantOf": null,
"sources": [
{ "sourceId": "SRC-SMTH", "location": "“三命通會” 卷二 論十干化氣",
"quote": "故丁與壬合 丁壬化木", "match": "EXACT", ... }
],
"engineRef": "..."
}
}
GET /api/v1/partners/v1/kb/release?domain=saju
คืนฉบับของฐานข้อมูลการตีความที่เผยแพร่อยู่ตอนนี้ ใช้ได้ฟรี หากละ domain จะเป็น saju (เช่น saju · ziwei · astro · dream · tarot)
curl "https://api.hrum.ai/api/v1/partners/v1/kb/release?domain=saju" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"version": "2026.10.09-3",
"hash": "sha256:24b9a2d9...",
"publishedAt": "2026-10-09T00:00:00.000Z",
"channel": "stable",
"counts": { "rules": 412, "interps": 1236 }
}
}
ตัวเลขข้างต้นเป็นตัวอย่าง หากเก็บผลลัพธ์ไว้ ให้ดึงใหม่เมื่อ hash เปลี่ยน
รหัสข้อผิดพลาด
นอกจากข้อผิดพลาดทั่วไป:
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 404 | kb_saju_explain_not_enabled | บัญชีที่ไม่ได้ยื่นขอ (ใช้ร่วมกันทั้งสามเส้นทาง) |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | explain — วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว |
| 403 | KB_PREVIEW_NOT_ALLOWED | explain — บัญชีที่ไม่ได้รับอนุญาต channel: "preview" (ไม่คิดค่าบริการ) |
| 400 | KB_DOMAIN_UNKNOWN | release — domain ที่ไม่รองรับ |
| 404 | KB_RULE_NOT_FOUND | rules — id กฎที่ไม่มีอยู่ |
| 503 | KB_NOT_LOADED | ฉบับของฐานข้อมูลการตีความยังไม่ถูกโหลด ลองใหม่อีกครั้งในภายหลัง |
explain คิดค่าบริการเฉพาะการเรียกที่สำเร็จ การเรียกที่ล้มเหลวจะถูกบันทึกเป็น ₩0
API ส่งอีเมลของแอป
API สำหรับให้แอปที่อัปโหลดบน RIDM Apps ส่งอีเมลแจ้งธุรกรรม · บริการ เช่น ยืนยันการสมัคร · แจ้งคำสั่งซื้อ · รีเซ็ตรหัสผ่าน เรียกได้เฉพาะด้วยคีย์สำหรับแอป (HRUM_API_KEY คอนโซล > แอปของฉัน > เชื่อมต่อ AI) หากเรียกด้วยคีย์ API ทั่วไปจะตอบ 403 MAIL_APP_KEY_REQUIRED คอนเทนเนอร์ของแอปปิดพอร์ต SMTP ไว้ จึงให้ส่งอีเมลผ่าน API นี้
- ที่อยู่ผู้ส่งคือที่อยู่ส่งอีเมลของ RIDM Apps และชื่อผู้ส่งคือชื่อแอป (เปลี่ยนได้ที่คอนโซล > แอปของฉัน > อีเมล) ตามด้วย "(RIDM Apps)" (เช่น
달빛 베이커리 (RIDM Apps)) ชื่ออย่างธนาคาร · บัตร · แบรนด์ชำระเงิน หน่วยงานรัฐ (กรมสรรพากร · ตำรวจ · อัยการ · รัฐบาล · ไปรษณีย์ ฯลฯ) และ HRUM · RIDM ใช้เป็นชื่อผู้ส่งไม่ได้ อีเมลตอบกลับจะไปยังreplyToหรือที่อยู่ที่ตั้งไว้ในคอนโซล - ส่งได้เฉพาะพาร์ทเนอร์ที่มีบัญชีคอนโซลที่ยืนยันอีเมลแล้ว หากยังไม่ยืนยันจะตอบ 403
MAIL_EMAIL_UNVERIFIED - ส่งอีเมลโฆษณาไม่ได้ หากหัวเรื่องขึ้นต้นด้วย
(광고)จะถูกปฏิเสธด้วย 400 โฆษณาเพื่อการค้า เช่น แจ้งส่วนลด · กิจกรรม ต้องได้รับความยินยอมล่วงหน้าจากผู้รับและมีช่องทางปฏิเสธการรับตามมาตรา 50 ของพระราชบัญญัติเครือข่ายสารสนเทศและการสื่อสารของเกาหลี จึงอย่าส่งผ่าน API นี้ (ข้อตกลงข้อ 20-2) - ผู้รับ 1 คนคือ 1 รายการ ใส่ได้สูงสุด 10 คนต่อคำขอ และส่งแยกถึงแต่ละคนจึงไม่เห็นที่อยู่ของกันและกัน
- ที่อยู่ที่มีการตีกลับ (ที่อยู่ไม่มีอยู่จริง) หรือถูกรายงานสแปมจะไม่ถูกส่งอีกหลังจากนั้น และตอบเป็น
suppressedรายการนี้ไม่ถูกนับและไม่มีค่าบริการ - ประเภทอีเมล (
kind): ค่าเริ่มต้นคือtransactional(การแจ้งที่ต้องส่ง เช่น สมัคร · คำสั่งซื้อ · รหัสผ่าน) และส่งตามเดิม การแจ้งเตือนของแอปที่ผู้รับปิดได้ (ความคิดเห็นใหม่ · แจ้งการจอง ฯลฯ) ให้ส่งด้วย"kind": "notification"อีเมลนี้จะมีเฮดเดอร์ปฏิเสธการรับแบบคลิกเดียว (List-Unsubscribe,List-Unsubscribe-Post, RFC 8058) แนบมา จึงกด "ยกเลิกการรับ" ได้ทันทีในแอปอีเมลอย่าง Gmail ที่อยู่ที่ปฏิเสธการรับแล้วจะไม่ได้รับเฉพาะอีเมลnotificationของแอปนั้น และตอบเป็นsuppressed(ไม่ถูกนับและไม่มีค่าบริการ) อีเมลtransactionalที่ส่งไปที่อยู่เดียวกันและอีเมลของแอปอื่นยังส่งได้ตามเดิมnotificationก็ไม่ใช่อีเมลโฆษณา — โฆษณาส่งไม่ได้ไม่ว่าประเภทใด บันทึกการปฏิเสธการรับเก็บไว้ 3 ปี (1,095 วัน) หลังจากนั้นจะถูกลบ และอีเมลnotificationอาจถูกส่งไปที่อยู่เดิมได้อีก - ระงับอัตโนมัติ: หากใน 30 วันล่าสุด การรายงานสแปมมีตั้งแต่ 0.1% (ขั้นต่ำ 2 รายการ) ของจำนวนที่ส่ง หรือการตีกลับถาวรมีตั้งแต่ 5% (ขั้นต่ำ 10 รายการ) (หากส่งน้อยกว่า 200 รายการจะคำนวณเป็น 200 รายการ) จะระงับการส่งอีเมลของแอปนั้นทันทีและแจ้งให้ทราบ หากสงสัยว่ามีการแอบอ้าง · ฟิชชิงก็เช่นกัน ตัวแอปยังทำงานตามเดิม และระหว่างที่ระงับจะตอบ 403
MAIL_SUSPENDEDขอปลดได้ที่ contact@float.do (ข้อตกลงข้อ 20-2)
POST /api/v1/partners/v1/mail/send
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | จำเป็น | คำอธิบาย |
|---|---|---|---|
to | string | string[] | O | ที่อยู่ผู้รับ 1~10 รายการ ไม่รับที่อยู่ที่มีชื่อ (ชื่อ <ที่อยู่>) |
subject | string | O | หัวเรื่อง 1~200 ตัวอักษร ไม่มีการขึ้นบรรทัดใหม่ |
text | string | △ | เนื้อหา (ข้อความธรรมดา) ต้องมี text หรือ html อย่างใดอย่างหนึ่ง สูงสุด 100,000 ตัวอักษร |
html | string | △ | เนื้อหา (HTML) สูงสุด 200,000 ตัวอักษร จะถูกจัดระเบียบก่อนส่ง: ลบ script · style · iframe · ฟอร์ม · แอตทริบิวต์อีเวนต์ ลิงก์คงไว้เฉพาะ http(s) · mailto · tel และรูปภาพเฉพาะ https หากไม่มี text จะสร้างเนื้อหาข้อความธรรมดาจาก HTML แล้วส่งไปด้วย |
replyTo | string | ที่อยู่สำหรับรับอีเมลตอบกลับ หากไม่มีจะใช้ที่อยู่ที่ตั้งไว้ในคอนโซล หากไม่มีอีกจะส่งโดยไม่มีที่อยู่ตอบกลับ | |
attachments | object[] | ไฟล์แนบสูงสุด 3 ไฟล์ รวมไม่เกิน 512KB { "filename", "contentType", "content" } (content เป็น base64) รับเฉพาะ PDF · PNG · JPEG · GIF · WebP · TXT · CSV · ICS | |
kind | string | transactional (ค่าเริ่มต้น) · notification หากเป็น notification จะแนบเฮดเดอร์ปฏิเสธการรับแบบคลิกเดียว และข้ามที่อยู่ที่ปฏิเสธการรับของแอปนั้น (suppressed) |
ตัวอย่างคำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/mail/send \
-H "Content-Type: application/json" \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-d '{
"to": "user@example.com",
"subject": "Welcome aboard",
"text": "Your sign-up is complete. Get started with the link below.",
"html": "<p>Your sign-up is complete.</p><p><a href=\"https://myapp.ridm.ai\">Get started</a></p>"
}'
ตัวอย่างการตอบกลับ
{
"success": true,
"data": {
"requestId": "7f1c2a3e-…",
"results": [ { "to": "user@example.com", "status": "sent", "messageId": "<…>" } ],
"sent": 1,
"chargedWon": 0
}
}
status เป็นหนึ่งใน sent (เซิร์ฟเวอร์อีเมลรับแล้ว) · failed (ส่งไม่ได้ — ไม่มีค่าบริการ) · suppressed (ข้ามเพราะเป็นที่อยู่ที่ตีกลับ · ถูกรายงานสแปม หรือเป็นที่อยู่ที่ปฏิเสธการรับอีเมล notification ของแอปนั้น)
เพดานและราคา
| รายการ | รายละเอียด |
|---|---|
| จำนวนที่รวมต่อเดือน | รวมอยู่ในแพ็กเกจ (ฟรี 100 รายการ · Basic 1,000 รายการ · Pro 3,000 รายการ ต่อแอป รีเซ็ตวันที่ 1 ของทุกเดือนตามเวลาเกาหลี) ส่วนที่รวมอยู่ไม่มีค่าบริการแยก |
| เมื่อเกินส่วนที่รวม | แพ็กเกจฟรีจะหยุดจนถึงวันที่ 1 ของเดือนถัดไป แพ็กเกจที่มีค่าใช้จ่ายจะส่งต่อได้ในราคา 1 วอนต่อรายการ (ไม่รวม VAT · รวม VAT 1.1 วอน) เฉพาะเมื่อเปิดการส่งเพิ่มเติมในคอนโซล หักจากเครดิตทันทีหลังส่ง เฉพาะรายการที่เซิร์ฟเวอร์อีเมลรับแล้ว |
| เพดานรายวัน | ค่าเริ่มต้น 500 รายการต่อแอป (ในคอนโซล 1~5,000 รายการ) รีเซ็ตเที่ยงคืนตามเวลาเกาหลี |
| เพดานต่อนาที | 30 รายการต่อนาทีต่อแอป |
ข้อผิดพลาด
| HTTP | code | คำอธิบาย |
|---|---|---|
| 400 | MAIL_INVALID | คำขอไม่ถูกต้อง เหตุผลอยู่ใน reason (invalid_recipient, too_many_recipients, subject_invalid, advertising_not_allowed, body_required, attachment_type_not_allowed, attachments_too_large ฯลฯ) |
| 402 | insufficient_credit | เครดิตไม่พอจ่ายส่วนการส่งเพิ่มเติม จะไม่ส่งอะไรเลย |
| 403 | MAIL_APP_KEY_REQUIRED | เรียกด้วยคีย์ที่ไม่ใช่คีย์สำหรับแอป |
| 403 | APP_NOT_ACTIVE | แอปที่ผูกกับคีย์ไม่ได้อยู่ในสถานะให้บริการ |
| 402 | MAIL_OVERAGE_UNPAID | ค่าอีเมลส่วนเพิ่มที่ยังหักไม่ได้มากกว่ายอดคงเหลือ เมื่อเติมเงินจะหักค่าค้างแล้วเปิดใหม่ (การส่งภายในจำนวนที่รวมยังทำได้ตามเดิม) |
| 403 | MAIL_EMAIL_UNVERIFIED | ไม่มีบัญชีคอนโซลที่ยืนยันอีเมลแล้ว |
| 403 | MAIL_SUSPENDED | การส่งอีเมลของแอปนี้ถูกระงับเพราะเกินเกณฑ์การรายงานสแปม · การตีกลับ หรือผู้ดูแลระบบระงับ |
| 429 | MAIL_RATE_LIMITED | เกินเพดานต่อนาที ส่งใหม่หลัง retryAfterSeconds |
| 429 | MAIL_DAILY_CAP_EXCEEDED | เกินเพดานรายวัน จะเปิดใหม่เที่ยงคืนตามเวลาเกาหลี |
| 429 | MAIL_MONTHLY_LIMIT | ใช้จำนวนที่รวมของเดือนนี้หมดแล้ว (แพ็กเกจฟรี หรือปิดการส่งเพิ่มเติม) |
| 503 | MAIL_UNAVAILABLE | ใช้เซิร์ฟเวอร์อีเมลไม่ได้ ลองใหม่อีกครั้งในภายหลัง |
แสดงจำนวนผู้ออนไลน์ตอนนี้บนเว็บเมตาเวิร์ส
ฟีเจอร์ฟรีที่แสดง "ตอนนี้มี N คนออนไลน์" บนพื้นที่ 3D บนเว็บอย่าง Three.js หรือหน้าเว็บทั่วไป เมื่อลงทะเบียนเว็บไซต์ที่คอนโซล > จำนวนผู้ออนไลน์ จะได้คีย์เว็บไซต์สาธารณะ (pk_presence_…) และสคริปต์หนึ่งบรรทัด เรียกจากเบราว์เซอร์ได้ทันทีโดยไม่ต้องใช้คีย์ · เข้าสู่ระบบ
- ที่อยู่ที่อนุญาต: นับเฉพาะสัญญาณที่มาจากที่อยู่ที่ระบุตอนลงทะเบียน (https ไม่มีพาธ สูงสุด 5 รายการ) โดเมนของที่อยู่เว็บไซต์ต้องอยู่ในที่อยู่ที่อนุญาตด้วย
- เกณฑ์การนับ: แต่ละแท็บส่งสัญญาณทุก 30 วินาที และนับแท็บที่ส่งสัญญาณมาภายใน 75 วินาทีล่าสุดว่า "ออนไลน์" เมื่อแท็บถูกซ่อนจะหยุดส่งสัญญาณ และเมื่อปิดจะถูกนำออกทันที
- ป้องกันการปั่นตัวเลข: สัญญาณจากแท็บเดียวกันนับครั้งเดียว (ละเว้นการซ้ำภายใน 10 วินาที) และมีเพดานจำนวนแท็บที่เพิ่มขึ้นจาก IP เดียว และจำนวนสัญญาณต่อเว็บไซต์ ไม่นับสัญญาณจาก User-Agent ว่าง · เครื่องมืออัตโนมัติ · เบราว์เซอร์แบบ headless
ใส่สคริปต์
ใส่สคริปต์ที่ได้จากคอนโซล > จำนวนผู้ออนไลน์ลงในหน้าหนึ่งบรรทัด และใส่ data-hrum-online ในตำแหน่งที่จะแสดงตัวเลข
<script src="https://hrum.ai/p/presence.js" data-key="pk_presence_YOUR_SITE_KEY" async></script>
<span data-hrum-online></span> online now
แค่นี้ก็เรียบร้อย ทุกแท็บที่เปิดหน้าจะส่งสัญญาณทันทีหนึ่งครั้ง และหลังจากนั้นทุก 30 วินาที แล้วใส่จำนวนผู้ออนไลน์ที่ได้กลับมาลงในทุกองค์ประกอบที่มี data-hrum-online ก่อนตัวเลขมาจะว่างไว้
- คีย์เว็บไซต์ (
pk_presence_…) เป็นคีย์สาธารณะ ใส่ในซอร์สของหน้าได้ตามเดิม แม้เว็บไซต์อื่นนำไปใช้ หากไม่ใช่ที่อยู่ที่อนุญาตก็จะไม่ถูกนับ - หากแท็บมองไม่เห็น (ไปแท็บอื่นหรือย่อแอป) จะหยุดส่งสัญญาณ และเมื่อกลับมามองเห็นจะส่งทันทีหนึ่งครั้ง เมื่อปิดหรือออกจากแท็บจะส่งสัญญาณออกหนึ่งครั้ง และแม้สัญญาณนี้ส่งไม่ถึง ก็จะถูกนำออกหลัง 75 วินาที
- รีเฟรชในแท็บเดียวกันก็นับเป็นหนึ่งคน แต่ละแท็บสร้างค่าเซสชันแบบสุ่มและเก็บไว้เฉพาะใน
sessionStorageของแท็บนั้น ไม่ส่งคุกกี้ · ข้อมูลการเข้าสู่ระบบ - แม้คีย์ผิดหรือเครือข่ายถูกบล็อก ก็ไม่เกิดข้อผิดพลาด เพียงปล่อยตัวเลขว่างไว้ แม้ใส่สคริปต์ซ้ำสองครั้ง (ตัวจัดการแท็ก + ใส่เอง ฯลฯ) ก็ใช้เพียงตัวที่ทำงานก่อน จึงไม่นับซ้ำ
ใช้ตัวเลขเอง
สคริปต์จะสร้าง window.HrumPresence ใช้เมื่อวาดตัวเลขบนหน้าจอของเราเอง เช่น ป้าย 3D · แบดจ์
HrumPresence.onChange(function (online) {
// online: current visitor count (integer)
myScene.setVisitorCount(online);
});
HrumPresence.online; // last number received, null if none yet
HrumPresence.refresh(); // send once more now and update the number
HrumPresence.stop(); // stop counting and send a leave signal
onChange ถูกเรียกเฉพาะเมื่อตัวเลขเปลี่ยน หากลงทะเบียนหลังได้รับตัวเลขแล้ว จะถูกเรียกทันทีหนึ่งครั้ง หากใส่สคริปต์แบบ async อาจยังไม่มี HrumPresence จึงต้องรอจนมีแล้วจึงลงทะเบียน
function whenPresence(fn) {
if (window.HrumPresence) return fn(window.HrumPresence);
setTimeout(function () { whenPresence(fn); }, 200);
}
whenPresence(function (p) { p.onChange(function (n) { myScene.setVisitorCount(n); }); });
ตัวอย่าง Three.js
hrum.ai/samples/presence-three/?key=pk_presence_… — ตัวอย่างที่ติดแบดจ์ "ตอนนี้ ○ คน" และป้าย 3D ในห้องเล็กๆ ที่สร้างด้วย Three.js ป้ายและรูปคนรอบโต๊ะวาดจากตัวเลขที่ได้ทาง onChange นำซอร์สของหน้าไปใช้เป็นจุดเริ่มต้นได้ตามเดิม เมื่อใส่ในเว็บไซต์ของเรา ให้ใช้คีย์ที่ใส่ที่อยู่ของเว็บไซต์นั้นไว้ในที่อยู่ที่อนุญาต
อ่านเฉพาะตัวเลขจากนอกหน้า
หากต้องการเพียงตัวเลขจากนอกหน้า เช่น แดชบอร์ด · บอต ให้ใช้ API ดึงข้อมูล ไม่ส่งสัญญาณจึงไม่ถูกนับรวมในจำนวนผู้ออนไลน์
curl https://api.hrum.ai/api/v1/partners/v1/presence/sites/pk_presence_…/online
# {"success":true,"data":{"online":42,"source":"beacon","updatedAt":"2026-10-31T01:23:45.000Z"}}
หากตัวเลขไม่ขึ้น ให้ตรวจว่าที่อยู่ (origin) ของหน้าปัจจุบันอยู่ในที่อยู่ที่อนุญาตหรือไม่ ที่อยู่ที่อนุญาตรับเฉพาะ https และต้องตรงกันถึงพอร์ต
เอนด์พอยต์
| เมธอด · เส้นทาง | คำอธิบาย |
|---|---|
POST /api/v1/partners/v1/presence/beat | ส่งสัญญาณ เนื้อหา { "siteKey", "sid" } (JSON text/plain หรือ application/json ไม่เกิน 1KB) sid คือค่าสุ่มที่สร้างต่อแท็บ (16~64 ตัวอักษร อังกฤษ · ตัวเลข · _ · -) หาก Origin ไม่อยู่ในที่อยู่ที่อนุญาตจะได้ 403 การตอบกลับ { online } |
POST /api/v1/partners/v1/presence/leave | นำแท็บนั้นออกทันทีเมื่อปิดแท็บ (navigator.sendBeacon) เนื้อหาเหมือน beat และการตอบกลับคือ 204 |
GET /api/v1/partners/v1/presence/sites/{siteKey}/online | ดึงจำนวนผู้ออนไลน์ตอนนี้ { online, source, updatedAt } source คือ server (ค่าที่เซิร์ฟเวอร์ส่ง) หรือ beacon (ผลรวมสัญญาณจากสคริปต์) เรียกได้จากทุกหน้า (CORS *) และแคช 10 วินาที คีย์ที่ถูกยกเลิกได้ 404 |
POST /api/v1/partners/v1/presence/sites/{siteKey}/count | ส่งตัวเลขจากเซิร์ฟเวอร์ (ด้านล่าง) ต้องใช้คีย์เซิร์ฟเวอร์ ครั้งเดียวต่อนาที ส่งจำนวนคนแยกตามห้อง rooms ไปด้วยได้ |
GET /api/v1/partners/v1/presence/sites/{siteKey}/rooms | จำนวนคนแยกตามห้องที่เซิร์ฟเวอร์ห้องใช้เลือกห้องที่จะเข้า (ด้านล่าง) ต้องใช้คีย์เซิร์ฟเวอร์ ไม่เปิดเผยต่อสาธารณะ |
GET /api/v1/partners/v1/presence/directory | รายการเว็บไซต์ที่ยินยอมแบ่งปันกับเมตาโมอา (ชื่อ · ที่อยู่ · จำนวนผู้ออนไลน์) แคช 30 วินาที |
ตัวอย่างการตอบกลับ
// POST /presence/beat
{ "success": true, "data": { "online": 12 } }
// GET /presence/sites/pk_presence_…/online
{ "success": true, "data": { "online": 12, "source": "beacon", "updatedAt": "2026-10-31T09:00:00.000Z" } }
// GET /presence/directory
{ "success": true, "data": [ { "label": "우주 광장", "siteUrl": "https://example.com/world", "online": 12 } ] }
ส่งตัวเลขจากเซิร์ฟเวอร์
หากเซิร์ฟเวอร์ของเรา (เซิร์ฟเวอร์เกม · เซิร์ฟเวอร์เรียลไทม์ ฯลฯ) รู้จำนวนผู้ออนไลน์อยู่แล้ว เซิร์ฟเวอร์ส่งตัวเลขมาเองได้ ออกคีย์เซิร์ฟเวอร์ (sk_presence_…) ต่อเว็บไซต์ได้ที่คอนโซล > จำนวนผู้ออนไลน์ คีย์เซิร์ฟเวอร์จะแสดงเพียงครั้งเดียวตอนออก จึงให้เก็บไว้ในตัวแปรสภาพแวดล้อมของเซิร์ฟเวอร์ และอย่าใส่ในโค้ดของหน้า · เบราว์เซอร์ หากออกใหม่ คีย์เซิร์ฟเวอร์เดิมจะหยุดทันที
POST /api/v1/partners/v1/presence/sites/{siteKey}/count· เนื้อหา{ "online": จำนวนเต็ม }(0~100,000) · เฮดเดอร์X-Presence-Secret: sk_presence_…หรือAuthorization: Bearer sk_presence_…การตอบกลับ{ online, reportedAt }- ใช้เฉพาะเซิร์ฟเวอร์ → เซิร์ฟเวอร์ จึงไม่เปิด CORS ของเบราว์เซอร์ หากส่งด้วยคีย์สาธารณะ (
pk_presence_…) จะได้ 401 - รับได้ครั้งเดียวต่อนาทีต่อเว็บไซต์ หากส่งถี่กว่านั้นจะตอบ 429 พร้อม
Retry-After(วินาที) - หากมีค่าที่เซิร์ฟเวอร์ส่งภายใน 5 นาทีล่าสุด จะใช้ค่านั้นเป็นจำนวนผู้ออนไลน์ (
source: "server") เมื่อเกิน 5 นาทีจะกลับไปใช้ผลรวมสัญญาณจากสคริปต์ (source: "beacon") หากไม่มีสัญญาณด้วยจะเป็น 0 - หากค่าพุ่งขึ้นมากกะทันหันจากค่าก่อนหน้า จะแสดงตามเดิมแต่บันทึกไว้เพื่อการตรวจสอบของฝ่ายปฏิบัติการ
- ในเนื้อหาให้ใส่เฉพาะ
onlineและroomsด้านล่าง หากมีฟิลด์อื่นจะได้ 400
จำนวนคนแยกตามห้อง (ไม่บังคับ)
หากเป็นเซิร์ฟเวอร์ที่แบ่งห้อง (ช่อง · อินสแตนซ์) ใช้ ก็ส่งจำนวนคนและความจุของแต่ละห้องไปในเนื้อหา count เดียวกันได้ เซิร์ฟเวอร์ห้องจะอ่านกลับด้วย GET …/rooms เมื่อเลือกห้องให้คนใหม่ ตัวเลขแยกตามห้องอ่านได้ด้วยคีย์เซิร์ฟเวอร์เท่านั้น และไม่ปรากฏในการดึงข้อมูลสาธารณะ (online · directory) และ presence.js จำนวนผู้ออนไลน์ทั้งหมดให้ส่งแยกด้วย online เหมือนตอนนี้ (ไม่คำนวณแทนด้วยผลรวมของห้อง)
POST /api/v1/partners/v1/presence/sites/pk_presence_…/count
X-Presence-Secret: sk_presence_…
Content-Type: application/json
{
"online": 98,
"rooms": [
{ "id": "studio-1", "n": 30, "cap": 30 },
{ "id": "studio-2", "n": 28, "cap": 30 },
{ "id": "studio-3", "n": 40, "cap": 50 }
]
}
// 200
{ "success": true, "data": { "online": 98, "reportedAt": "2026-10-31T09:00:00.000Z" } }
roomsไม่เกิน 200 รายการidคืออังกฤษ · ตัวเลข ·_·-1~64 ตัวอักษร (ห้าม#· ช่องว่าง) และห้ามซ้ำกันในเนื้อหาเดียวnคือจำนวนเต็ม 0~100,000capคือจำนวนเต็ม 1~100,000 หากอ็อบเจกต์ห้องมีฟิลด์อื่นจะได้ 400- หาก
nมากกว่าcapจะได้ 400PRESENCE_ROOM_OVER_CAPการไม่รับคนเกินความจุเป็นหน้าที่ของเซิร์ฟเวอร์ห้อง ค่าที่เกินจึงไม่ถูกเก็บ ข้อผิดพลาดรูปแบบอื่นจะแจ้งด้วย 400PRESENCE_BAD_REQUESTและfield(เช่นrooms[3].id) หากได้ 400 ตัวเลขรวมก็จะไม่ถูกเก็บ - ทุกครั้งที่ส่ง รายการห้องทั้งหมดจะถูกแทนที่ ห้องที่ไม่อยู่ในการรายงานครั้งถัดไปจะหายไป และหากส่งโดยไม่มี
roomsจะถือว่าไม่มีห้อง - หากไม่มีการรายงานใหม่ภายใน 2 นาทีหลังการรายงานล่าสุด รายการห้องจะถูกอ่านเป็นรายการว่าง (
[]) แยกจากเกณฑ์ 5 นาทีของตัวเลขรวม ส่งทุกนาทีก็จะไม่ขาดช่วง - การรายงานที่ติดข้อจำกัด 1 ครั้งต่อนาที (429) จะไม่เปลี่ยนรายการห้องด้วย
GET /api/v1/partners/v1/presence/sites/pk_presence_…/rooms
Authorization: Bearer sk_presence_…
// 200
{ "success": true, "data": {
"rooms": [
{ "id": "studio-1", "n": 30, "cap": 30, "free": 0 },
{ "id": "studio-2", "n": 28, "cap": 30, "free": 2 },
{ "id": "studio-3", "n": 40, "cap": 50, "free": 10 }
],
"reportedAt": "2026-10-31T09:00:00.000Z"
} }
- เฮดเดอร์เหมือน
count(X-Presence-SecretหรือAuthorization: Bearer) รับเฉพาะคีย์เซิร์ฟเวอร์ของเว็บไซต์นั้น — คีย์สาธารณะ คีย์เซิร์ฟเวอร์ของเว็บไซต์อื่น หรือไม่มีคีย์ได้ 401 เว็บไซต์ที่ถูกยกเลิกได้ 404 roomsเรียงตามลำดับตัวเลขของid(studio-2มาก่อนstudio-10) และfree=cap − nหากต้องการเติมห้องตั้งแต่หมายเลขต่ำก่อน ให้เลือกห้องแรกที่free > 0reportedAtคือเวลาที่ได้รับการรายงานล่าสุด (หากไม่เคยมีการรายงานเป็นnull) แม้เกิน 2 นาทีแล้วรายการห้องว่าง ก็ใช้ค่านี้รู้ได้ว่าได้รับครั้งล่าสุดเมื่อใด- ใช้เฉพาะเซิร์ฟเวอร์ → เซิร์ฟเวอร์ จึงไม่เปิด CORS ของเบราว์เซอร์และไม่แคช (
Cache-Control: no-store) ได้สูงสุด 60 ครั้งต่อนาทีต่อเว็บไซต์ หากเกินจะได้ 429 พร้อมRetry-After - รับเฉพาะ id ห้องและตัวเลขจำนวนคน · ความจุ อย่าใส่ข้อมูลผู้ใช้
เก็บคีย์เซิร์ฟเวอร์ไว้บนเซิร์ฟเวอร์เท่านั้น หากใส่ sk_presence_… ในโค้ดเบราว์เซอร์ · แอป · ที่เก็บสาธารณะ ใครก็เปลี่ยนจำนวนผู้ออนไลน์ได้ ให้เก็บในตัวแปรสภาพแวดล้อมหรือที่เก็บความลับ และหากรั่วไหล ให้ออกใหม่ทันทีที่คอนโซล > จำนวนผู้ออนไลน์
โปรดส่งนาทีละครั้ง หากไม่มีค่าใหม่มา 5 นาที จะกลับไปใช้ผลรวมสัญญาณจากสคริปต์ ใช้ร่วมกับสคริปต์บนเบราว์เซอร์ได้ และในกรณีนั้นแบดจ์บนหน้าจะแสดงตัวเลขที่เซิร์ฟเวอร์ส่ง
curl
curl -X POST "https://api.hrum.ai/api/v1/partners/v1/presence/sites/pk_presence_…/count" \
-H "Content-Type: application/json" \
-H "X-Presence-Secret: $HRUM_PRESENCE_SECRET" \
-d '{"online": 128}'
# {"success":true,"data":{"online":128,"reportedAt":"2026-10-31T01:23:45.000Z"}}
Node (เซิร์ฟเวอร์ WebSocket)
// Node 18+ (built-in fetch), next to your `ws` server
setInterval(() => {
fetch("https://api.hrum.ai/api/v1/partners/v1/presence/sites/pk_presence_…/count", {
method: "POST",
headers: { "Content-Type": "application/json", "X-Presence-Secret": process.env.HRUM_PRESENCE_SECRET },
body: JSON.stringify({ online: wss.clients.size }),
}).catch(() => {}); // a missed report is fine: the next one comes in 60 s
}, 60_000);
Cloudflare Workers (Durable Object)
// One Durable Object per room holds the WebSockets and reports their number every 60 s.
// wrangler secret put HRUM_PRESENCE_SECRET ; vars: HRUM_SITE_KEY = "pk_presence_…"
import { DurableObject } from "cloudflare:workers";
const API = "https://api.hrum.ai/api/v1/partners/v1/presence";
export class Room extends DurableObject {
async fetch(request) {
const [client, server] = Object.values(new WebSocketPair());
this.ctx.acceptWebSocket(server);
if (!(await this.ctx.storage.getAlarm())) await this.ctx.storage.setAlarm(Date.now() + 60_000);
return new Response(null, { status: 101, webSocket: client });
}
async alarm() {
const online = this.ctx.getWebSockets().length;
await fetch(`${API}/sites/${this.env.HRUM_SITE_KEY}/count`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Presence-Secret": this.env.HRUM_PRESENCE_SECRET },
body: JSON.stringify({ online }),
}).catch(() => {});
// keep reporting while anyone is connected; after the last one leaves, 0 was the final report
if (online > 0) await this.ctx.storage.setAlarm(Date.now() + 60_000);
}
}
Supabase (Realtime Presence)
Edge Function จะเข้าไปในช่องที่ผู้ใช้ track() อยู่ นับจำนวนคีย์ presence แล้วส่ง และ pg_cron เรียกทุก 1 นาที คีย์มีหนึ่งคีย์ต่อการเชื่อมต่อ หากต้องการนับคนหนึ่งคนเพียงครั้งเดียว ให้ฝั่งผู้ใช้สร้างช่องด้วย config: { presence: { key: userId } }
// supabase/functions/presence-count/index.ts
// supabase secrets set HRUM_PRESENCE_SECRET=sk_presence_… HRUM_SITE_KEY=pk_presence_…
import { createClient } from "jsr:@supabase/supabase-js@2";
const API = "https://api.hrum.ai/api/v1/partners/v1/presence";
Deno.serve(async () => {
const supabase = createClient(Deno.env.get("SUPABASE_URL")!, Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!);
const channel = supabase.channel("room-1"); // the channel name your clients use
const online = await new Promise<number>((resolve) => {
const count = () => resolve(Object.keys(channel.presenceState()).length);
channel.on("presence", { event: "sync" }, count).subscribe();
setTimeout(count, 5_000); // no sync within 5 s: report what is there
});
await supabase.removeChannel(channel);
const res = await fetch(`${API}/sites/${Deno.env.get("HRUM_SITE_KEY")}/count`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Presence-Secret": Deno.env.get("HRUM_PRESENCE_SECRET")! },
body: JSON.stringify({ online }),
});
return new Response(null, { status: res.ok ? 204 : 502 });
});
-- every minute (pg_cron + pg_net); project_url and service_role_key stored in Vault
select cron.schedule('hrum-presence-count', '* * * * *', $$
select net.http_post(
url := (select decrypted_secret from vault.decrypted_secrets where name = 'project_url') || '/functions/v1/presence-count',
headers := jsonb_build_object('Authorization', 'Bearer ' ||
(select decrypted_secret from vault.decrypted_secrets where name = 'service_role_key'))
);
$$);
การแบ่งปันกับเมตาโมอา
หากเปิด "แสดงในไดเรกทอรีเมตาโมอา" ในคอนโซล ชื่อ · ที่อยู่ · จำนวนผู้ออนไลน์ตอนนี้ของเว็บไซต์นั้นจะแสดงในไดเรกทอรีที่ HRUM ดำเนินการ เช่น เมตาโมอา หากที่อยู่เว็บไซต์ไม่ตรงกับที่อยู่ที่อนุญาตจะไม่แสดง ปิดได้ทุกเมื่อ
ข้อมูลส่วนบุคคล
- ไม่เก็บที่อยู่ IP และ User-Agent ของผู้เข้าชม IP ใช้ในหน่วยความจำชั่วครู่เพื่อคำนวณป้องกันการใช้ในทางที่ผิดเท่านั้น และไม่บันทึก
- บนเซิร์ฟเวอร์เหลือเพียงแฮชเซสชัน
sha256(siteKey + ":" + sid)และเวลาสัญญาณล่าสุด ซึ่งจะถูกลบเมื่อผ่านไป 10 นาที ไม่ใช้คุกกี้ - "ออนไลน์" คือจำนวนแท็บที่ส่งสัญญาณมาภายใน 75 วินาทีล่าสุด
ข้อผิดพลาด
| HTTP | code | คำอธิบาย |
|---|---|---|
| 400 | PRESENCE_BAD_REQUEST · INVALID_BODY | รูปแบบ siteKey · sid ไม่ถูกต้องหรือเนื้อหาไม่ใช่ JSON |
| 401 | PRESENCE_SECRET_REQUIRED | ไม่มีคีย์เซิร์ฟเวอร์หรือไม่ถูกต้อง (รวมกรณีส่งด้วยคีย์สาธารณะ) — เฉพาะ count |
| 403 | PRESENCE_ORIGIN_NOT_ALLOWED | ไม่มี Origin หรือไม่อยู่ในที่อยู่ที่อนุญาต |
| 404 | PRESENCE_SITE_NOT_FOUND | คีย์ที่ไม่มีอยู่หรือถูกยกเลิกแล้ว |
| 413 | PAYLOAD_TOO_LARGE | เนื้อหาเกิน 1KB |
| 429 | PRESENCE_RATE_LIMITED | สัญญาณมากเกินไป หรือส่ง count ซ้ำภายใน 1 นาที (Retry-After) ส่งใหม่อีกครั้งในภายหลัง |
API ยืนยันตัวตน
API ยืนยันตัวตนสำหรับจัดการบัญชีคอนโซล
POST /api/v1/partners/v1/console/auth/login
เข้าสู่ระบบด้วยอีเมลและรหัสผ่าน การสมัครสมาชิกใหม่ด้วยบัญชีโซเชียล ("provider": "google" · "apple", POST …/console/auth/google · /apple) ไม่รับตั้งแต่ 2026-10-17 และตอบ 410 SOCIAL_SIGNUP_DISABLED ผู้ที่สมัครด้วยบัญชีโซเชียลไว้แล้วยังเข้าสู่ระบบได้ตามเดิม
คำขอ (อีเมล)
curl -X POST https://api.hrum.ai/api/v1/partners/v1/console/auth/login \
-H "Content-Type: application/json" \
-d '{
"provider": "email",
"email": "[email protected]",
"password": "your-password"
}'
การตอบกลับ
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": "user-123",
"email": "[email protected]",
"displayName": "John Doe",
"provider": "email"
}
}
}
user.provider เป็นหนึ่งใน email · apple · google
POST /api/v1/partners/v1/console/auth/register
ลงทะเบียนบัญชีใหม่
คำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/console/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "secure-password",
"displayName": "John Doe",
"agreements": { "terms": true, "privacy": true }
}'
password 8~128 ตัวอักษร displayName (ชื่อที่แสดงหรือชื่อบริษัท) 2~50 ตัวอักษร agreements.terms · agreements.privacy ต้องเป็น true (หากไม่มีหรือเป็น false จะได้ 400) agreements.aiTraining (boolean) ไม่บังคับ agreements.marketing (boolean ไม่บังคับ) คือความยินยอมรับอีเมลแนะนำฟีเจอร์ใหม่ · สิทธิประโยชน์ หากไม่ส่งหรือเป็น false จะบันทึกว่าไม่ยินยอม
การตอบกลับ
{
"success": true,
"data": {
"message": "인증 메일을 발송했어요" // "Verification email sent"
}
}
POST /api/v1/partners/v1/console/auth/verify-email
ยืนยันอีเมลให้เสร็จสมบูรณ์ ส่งโทเค็นจากอีเมลยืนยันพร้อมรหัสผ่านที่ตั้งไว้ตอนสมัครสมาชิก
คำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/console/auth/verify-email \
-H "Content-Type: application/json" \
-d '{
"token": "token-from-verification-email",
"password": "secure-password"
}'
การตอบกลับ
{
"success": true,
"data": {
"message": "이메일 인증이 완료되었어요" // "Email verification complete"
}
}
หากโทเค็นไม่ถูกต้อง หมดอายุ หรือรหัสผ่านไม่ตรงจะได้ 400 EMAIL_VERIFY_FAILED ลิงก์ในอีเมลยืนยัน (GET /api/v1/partners/v1/console/auth/verify-email?token=…) ไม่ได้ยืนยัน แต่เพียงเปลี่ยนเส้นทาง 302 ไปยัง https://console.hrum.ai/verify-email.html?token=… — เมื่อป้อนรหัสผ่านในหน้านั้น POST ข้างต้นจะถูกเรียก
จัดการคอนโซลด้วย AI
เครื่องมือเขียนโค้ดด้วย AI อย่าง Claude Code · Cursor · Codex ทำงานในคอนโซลแทนได้ การดึงข้อมูล AI ทำได้ทันที ส่วนงานที่มีการเปลี่ยนแปลง เช่น ออกคีย์ · ลิงก์เติมเงิน · สมัครโฮสติ้ง จะดำเนินการได้เฉพาะเมื่อคนกด "ยินยอม" บนหน้าจอขอความยินยอมในคอนโซล เซิร์ฟเวอร์ปฏิเสธการเขียนที่ไม่มีรหัสความยินยอม จึงไม่มีเส้นทางที่ข้ามความยินยอมของคนได้ ข้อยกเว้นมีเพียง hosting_ops ด้านล่าง ซึ่งเปิดเฉพาะกับโทเค็นที่คนติ๊กไว้ตอนออก
โทเค็นจัดการคอนโซล
- โทเค็นเฉพาะที่ AI ใช้ (ขึ้นต้นด้วย
hrum_cm_) ส่งด้วยเฮดเดอร์คำขอAuthorization: Bearer hrum_cm_… - สิทธิ์พื้นฐานคือดึงข้อมูลเท่านั้น (บัญชี · รายการคีย์ · เครดิต · การใช้งาน · โฮสติ้ง · สถานะการสรุปยอดและโอนเงิน (settlement)) สิทธิ์เขียน 4 อย่าง —
keys(ออก · ออกใหม่ · ยกเลิกคีย์ API) ·credit(ลิงก์เติมเงิน · ดูตัวอย่างการคืนเงิน) ·hosting(สมัคร · ยกเลิกโฮสติ้ง) ·seller(ลิงก์ลงทะเบียนผู้ขาย) — คนจะติ๊กทีละรายการบนหน้าจอยินยอมการออกโทเค็น hosting_ops(โทเค็นปฏิบัติการ AI — ตั้งค่า · ลบตัวแปรสภาพแวดล้อมของแอปโฮสติ้งของเรา เริ่มดีพลอย · ดูสถานะดีพลอย ย้อนกลับ · รีสตาร์ต ดูล็อกรันไทม์) ก็ติ๊กบนหน้าจอยินยอมการออกโทเค็นเช่นกัน สิทธิ์นี้ไม่ต้องขอความยินยอมใหม่ทุกงาน วิธีใส่ตัวแปรสภาพแวดล้อม · คีย์ลับและชื่อที่อนุญาตในเส้นทาง AI อยู่ที่ คู่มือดีพลอย RIDM Apps — ใส่คีย์ลับด้วย AI และวิธีเริ่มดีพลอย · ดูสถานะดีพลอย · ดูล็อกอยู่ที่ ดีพลอยและดูล็อกด้วย AI- อายุการใช้งาน 30 วัน โทเค็นที่ยังใช้งานได้มีไม่เกิน 10 รายการต่อบัญชี
- ดูคำนำหน้า · สิทธิ์ · เวลาที่ใช้ล่าสุดในรายการ "โทเค็นจัดการคอนโซลด้วย AI" ของหน้า คีย์ API ในคอนโซล และยกเลิกได้ทันทีทุกเมื่อ ค่าโทเค็นจะไม่แสดงซ้ำอีก
ขั้นตอนการขอความยินยอม
- AI ใส่งานที่จะทำ (อะไร · จำนวนเงิน · เป้าหมาย) แล้วเรียก
POST /api/v1/partners/v1/console-ai/consentsและได้consentUrlกับcode - AI แสดงลิงก์ให้ผู้ใช้ (MCP อาจเปิดในเบราว์เซอร์ให้ด้วย)
- เมื่อผู้ใช้เปิดลิงก์ขณะเข้าสู่ระบบคอนโซลอยู่ จะเห็นป้าย "AI เป็นผู้ขอ" พร้อมรายละเอียดคำขอต้นฉบับ (จำนวนเงิน · เป้าหมาย · ชื่อ) ตรวจสอบแล้วกด "ยินยอม" ส่วนการชำระเงิน คนจะทำเองอีกครั้งที่หน้าต่างชำระเงินของ Toss ต่อจากนั้น
- AI ตรวจการอนุมัติด้วย
GET /console-ai/consents/{code}แล้วใส่consentCodeในเนื้อหาคำขอเขียนเพื่อดำเนินการต่อ
รหัสความยินยอมใช้ได้ครั้งเดียวและหมดอายุหลัง 10 นาที แฮชของรายละเอียดคำขอถูกผูกไว้กับรหัส หากเปลี่ยนจำนวนเงินหรือเป้าหมายหลังยินยอมจะถูกปฏิเสธ (CONSENT_MISMATCH)
โทเค็นแรกยังไม่มีโทเค็น จึงขอโดยไม่ต้องยืนยันตัวตนด้วย {"action":"token_issue","payload":{"scopes":["keys"]}} เมื่อใส่ pollSecret จากการตอบกลับในเฮดเดอร์ X-Consent-Poll-Secret เพื่อดึงสถานะ ค่าโทเค็นจะส่งมาครั้งเดียวในการดึงครั้งแรกหลังอนุมัติ account.email ในการตอบกลับเดียวกันคืออีเมลที่ปิดบางส่วนของบัญชีคอนโซลที่อนุมัติ หากไม่ใช่บัญชีของเรา ให้ยกเลิกโทเค็นนั้นในคอนโซล
curl -X POST https://api.hrum.ai/api/v1/partners/v1/console-ai/consents \
-H "Authorization: Bearer $HRUM_CONSOLE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"action":"credit_topup_link","payload":{"planKey":"credit_50000"}}'
# response data
{
"code": "cc_…",
"consentUrl": "https://console.hrum.ai/console-consent.html#c=cc_…",
"expiresAt": "2026-10-16T06:10:00.000Z",
"action": "credit_topup_link",
"display": [
{ "label": "충전 상품", "value": "credit_50000" },
{ "label": "결제 금액(부가세 포함)", "value": "55,000원" }
]
}
# after the user agrees
curl -X POST https://api.hrum.ai/api/v1/partners/v1/console-ai/credit/topup-link \
-H "Authorization: Bearer $HRUM_CONSOLE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"planKey":"credit_50000","consentCode":"cc_…"}'
เอนด์พอยต์
ทั้งหมดอยู่ใต้ /api/v1/partners/v1/console-ai
| เมธอด · เส้นทาง | สิ่งที่ทำ | สิทธิ์ | ความยินยอม |
|---|---|---|---|
POST /consents | สร้างคำขอความยินยอม ({action, payload}) | สิทธิ์ของ action (โทเค็นแรกไม่ต้องมี) | — |
GET /consents/{code} | สถานะความยินยอม: pending · approved · denied · expired · used | read (โทเค็นแรกใช้ poll secret) | — |
GET /me · GET /token | บัญชีของฉัน · สิทธิ์ของโทเค็นนี้ | read | — |
GET /status | เช็กลิสต์เริ่มต้น (สถานะ API · โฮสติ้ง · การชำระเงิน และการดำเนินการถัดไป) | read | — |
GET /keys | รายการคีย์ API (เฉพาะคำนำหน้า) | read | — |
GET /credit · GET /credit/transactions | ยอดเครดิตคงเหลือ · ประวัติ (offset, limit ≤ 100) | read | — |
GET /usage | การเรียก · การใช้จ่ายตามช่วงเวลา (from, to) | read | — |
GET /hosting | สมัครโฮสติ้งได้หรือไม่ · แพ็กเกจ · สถานะแอป | read | — |
GET /seller · GET /payouts | สถานะผู้ขาย (ไม่รวมข้อมูลส่วนตัว) · ประวัติการจ่ายเงิน | read | — |
POST /keys | ออกคีย์ API ({label?}) | keys | key_issue |
POST /keys/{id}/rotate | ออกคีย์ใหม่ + ปิดคีย์นี้ทันที | keys | key_rotate |
POST /keys/{id}/revoke | ยกเลิกคีย์ (ย้อนกลับไม่ได้) | keys | key_revoke |
POST /credit/topup-link | ลิงก์ชำระเงินเพื่อเติมเงิน ({planKey}) | credit | credit_topup_link |
POST /credit/refund-preview | คำนวณจำนวนเงินที่คืนได้ (ไม่ได้ยื่นขอ) | credit | credit_refund_preview |
POST /hosting/apply | สมัครโฮสติ้ง ({planKey, subdomain, recurringConsent?}) | hosting | hosting_apply |
POST /hosting/apps/{id}/cancel | ยกเลิกโฮสติ้ง | hosting | hosting_cancel |
POST /seller/apply-link | ลิงก์หน้าลงทะเบียนผู้ขาย | seller | seller_apply_link |
เนื้อหาของคำขอเขียนคือค่าเดียวกับ payload ของคำขอความยินยอม + consentCode คีย์ API ใหม่จะแสดงเพียงครั้งเดียวในการตอบกลับนั้น
หมายเลขบัตรและข้อมูลส่วนตัวของผู้ขายไม่รับผ่านเส้นทาง AI การชำระเงินด้วยบัตรทำในหน้าต่างชำระเงินของ Toss ส่วนข้อมูลส่วนตัว · บัญชีธนาคาร · การยอมรับข้อตกลงของผู้ขาย คนต้องป้อนเองบนหน้าจอคอนโซล หาก payload มีค่านอกเหนือรายการที่กำหนดจะถูกปฏิเสธด้วย 400 UNKNOWN_FIELD
รหัสข้อผิดพลาด
| รหัส | HTTP | ความหมาย |
|---|---|---|
MGMT_TOKEN_INVALID | 401 | ไม่มีโทเค็นหรือหมดอายุ · ถูกยกเลิก ให้ออกใหม่ |
MGMT_SCOPE_DENIED | 403 | โทเค็นนี้ไม่มีสิทธิ์เขียนที่จำเป็น (ฟิลด์ scope) ให้ติ๊กสิทธิ์นั้นแล้วออกใหม่ |
ACCOUNT_SUSPENDED | 403 | บัญชีถูกระงับ |
CONSENT_REQUIRED | 400 | คำขอเขียนไม่มี consentCode |
CONSENT_PENDING | 409 | คนยังไม่ได้ยินยอม |
CONSENT_DENIED | 403 | คนปฏิเสธ |
CONSENT_EXPIRED | 410 | หมดอายุเพราะเกิน 10 นาที |
CONSENT_USED | 409 | รหัสความยินยอมที่ใช้ไปแล้ว |
CONSENT_MISMATCH | 409 | รายละเอียดที่ยินยอม (จำนวนเงิน · เป้าหมาย) ต่างจากคำขอตอนนี้ |
CONSENT_NOT_FOUND | 404 | รหัสที่ไม่มีอยู่หรือเป็นรหัสของบัญชีอื่น |
INVALID_CONSENT_PAYLOAD | 400 | ค่า payload ไม่ถูกต้อง (ฟิลด์ field) |
UNKNOWN_FIELD | 400 | มีรายการที่ไม่รับผ่านเส้นทาง AI |
CONSENT_RATE_LIMITED | 429 | คำขอความยินยอมมากเกินไป |
MGMT_TOKEN_LIMIT | 409 | มีโทเค็นที่ใช้งานได้ 10 รายการแล้ว จึงออกเพิ่มไม่ได้ |
NOT_AVAILABLE | 404 | เมนูที่ยังไม่เปิด |
ใช้ผ่าน MCP
เมื่อติดตั้ง HRUM MCP (@hrum/mcp 0.2.0) จะใช้ขั้นตอนข้างต้นเป็นเครื่องมือได้ทันที โทเค็น · คีย์ API · poll secret จะไม่ปรากฏต่อโมเดล (ในบทสนทนา) และถูกเก็บไว้เฉพาะในโฟลเดอร์การตั้งค่าและ .env.local ของคอมพิวเตอร์เครื่องนี้
claude mcp add hrum -- npx -y https://console.hrum.ai/mcp/hrum-mcp-0.3.6.tgz
| เครื่องมือ | สิ่งที่ทำ |
|---|---|
hrum_ai_connect · hrum_ai_connect_status | สร้างลิงก์ขอความยินยอมสำหรับโทเค็นจัดการ → เมื่ออนุมัติจะเก็บโทเค็น (ไม่แสดงค่า) |
hrum_status · hrum_keys_list · hrum_credit · hrum_credit_history · hrum_usage · hrum_hosting_status · hrum_seller_status · hrum_payouts_list | ดึงข้อมูล |
hrum_consent_request · hrum_consent_status | ขอความยินยอมเพื่อเขียน · ตรวจสถานะ |
hrum_key_issue · hrum_key_rotate · hrum_key_revoke | ออก · ออกใหม่คีย์ (คีย์ใหม่เก็บเฉพาะใน .env.local) · ยกเลิก |
hrum_topup_link · hrum_refund_preview | ลิงก์เติมเงิน · จำนวนเงินที่คืนได้ |
hrum_hosting_apply · hrum_hosting_cancel · hrum_seller_apply_link | สมัคร · ยกเลิกโฮสติ้ง · ลิงก์ลงทะเบียนผู้ขาย |
API ดึงข้อมูล
API สำหรับดึงยอดเครดิตคงเหลือและสถานะการใช้งาน ต้องใส่ X-Partner-Api-Key ในเฮดเดอร์
GET /api/v1/partners/v1/credits/balance
ดึงยอดเครดิตคงเหลือปัจจุบัน
คำขอ
curl -X GET https://api.hrum.ai/api/v1/partners/v1/credits/balance \
-H "X-Partner-Api-Key: your-api-key"
การตอบกลับ
{
"success": true,
"data": {
"balanceWon": 25000,
"lastUpdated": "2026-10-09T05:12:30.000Z",
"estimatedMonthEndBalance": 15000,
"warningThreshold": 5000,
"lowBalanceActive": false
}
}
warningThreshold ต่างกันตามพาร์ทเนอร์ — max(₩5,000, 20% ของยอดเติมเงินแบบชำระเงินล่าสุด) lowBalanceActive บอกว่ายอดคงเหลือต่ำกว่าเกณฑ์นี้และอยู่ในสถานะเตือนยอดต่ำหรือไม่ ไม่มีเอนด์พอยต์สำหรับเติมเงินผ่าน API — เติมเงินได้ที่คอนโซล > ชำระเงิน API นี้ไม่มีรหัสข้อผิดพลาดเฉพาะ — มีเพียงข้อผิดพลาดทั่วไป
GET /api/v1/partners/v1/usage/logs?limit=50&offset=0
ดึงบันทึกการเรียก API เรียงจากล่าสุด แต่ละรายการมี id · timestamp · endpoint (ชื่อสั้น เช่น manseryeok) · statusCode · costWon · responseTimeMs (ตอนนี้เป็น null เสมอ) และจะมี idempotencyKey · model · endUserId · cachedTokens แนบมาเฉพาะเมื่อเกี่ยวข้อง
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
limit |
number | จำนวนรายการที่จะดึง (ค่าเริ่มต้น: 50 สูงสุด: 200) |
offset |
number | ออฟเซ็ต (ค่าเริ่มต้น: 0) |
endpoint |
string | กรองด้วยชื่อสั้นของเอนด์พอยต์ (เช่น manseryeok) หากเป็น all หรือละไว้คือทั้งหมด |
dateFrom · dateTo |
string | ช่วงเวลา (YYYY-MM-DD) หากละไว้ไม่มีข้อจำกัด |
คำขอ
curl "https://api.hrum.ai/api/v1/partners/v1/usage/logs?limit=50&offset=0&endpoint=manseryeok" \
-H "X-Partner-Api-Key: your-api-key"
การตอบกลับ
{
"success": true,
"data": {
"logs": [
{
"id": "12345",
"timestamp": "2026-08-10T14:30:00.000Z",
"endpoint": "manseryeok",
"statusCode": 200,
"costWon": 50,
"responseTimeMs": null,
"idempotencyKey": "order-8812"
}
],
"total": 1234,
"pagination": {
"limit": 50,
"offset": 0,
"hasMore": true
}
}
}
GET /api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31
ดึงสถิติการใช้งานตามช่วงเวลา หากละวันที่จะเป็นทั้งเดือนนี้ วันที่ใน dailyBreakdown อิงเวลาเกาหลี (KST)
พารามิเตอร์คำขอ
| พารามิเตอร์ | ชนิด | คำอธิบาย |
|---|---|---|
dateFrom |
string | วันที่เริ่มต้น (YYYY-MM-DD) |
dateTo |
string | วันที่สิ้นสุด (YYYY-MM-DD) |
คำขอ
curl "https://api.hrum.ai/api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31" \
-H "X-Partner-Api-Key: your-api-key"
การตอบกลับ
{
"success": true,
"data": {
"dateRange": { "from": "2026-08-01", "to": "2026-08-31" },
"totalCalls": 1234,
"totalCostWon": 6170,
"byEndpoint": [
{
"endpoint": "manseryeok",
"calls": 1234,
"costWon": 6170,
"percentOfTotal": 100
}
],
"dailyBreakdown": [
{
"date": "2026-08-10",
"calls": 150,
"costWon": 750
}
]
}
}
รหัสข้อผิดพลาด (บันทึกการใช้งาน · สรุป)
นอกจากข้อผิดพลาดทั่วไปแล้ว หากวันที่ไม่ใช่รูปแบบ YYYY-MM-DD หรือ limit · offset ติดลบ จะได้ 400 ที่ไม่มีรหัส การดึงข้อมูลไม่มีค่าใช้จ่าย
GET /api/v1/partners/v1/status/upstream
รวบรวมสถานะสาธารณะของผู้ให้บริการ AI ที่ HRUM ใช้ (OpenAI · Google Gemini · Anthropic Claude) แล้วคืนให้ ไม่ต้องใช้คีย์ API ไม่มีค่าใช้จ่าย และแคช 60 วินาที หน้าสถานะบริการใช้ค่านี้
curl https://api.hrum.ai/api/v1/partners/v1/status/upstream
{
"success": true,
"data": {
"providers": [
{ "name": "OpenAI", "indicator": "none", "description": "All Systems Operational", "url": "https://status.openai.com", "checkedAt": "2026-10-12T03:00:00.000Z" },
...
],
"checkedAt": "2026-10-12T03:00:00.000Z"
}
}
indicator: none (ปกติ) · minor · major · critical · unknown (อ่านสถานะไม่ได้) API นี้ไม่มีรหัสข้อผิดพลาดเฉพาะ
ทดลองใช้แบบผู้เยี่ยมชม
API ฟรีสำหรับทดลองซาจูโดยไม่ต้องเข้าสู่ระบบ
POST /api/v1/partners/v1/playground/manseryeok
คำนวณปฏิทินหมื่นปีโดยไม่ต้องยืนยันตัวตน เอนด์พอยต์ผู้เยี่ยมชม (ปฏิทินหมื่นปี · ผังดวงกำเนิด) รวมกันฟรี 5 ครั้งต่อ IP ต่อเดือน หากเกินจะได้ 429 GUEST_QUOTA_EXCEEDED
คำขอ
curl -X POST https://api.hrum.ai/api/v1/partners/v1/playground/manseryeok \
-H "Content-Type: application/json" \
-d '{
"year": 1990,
"month": 1,
"day": 15,
"hour": 14,
"minute": 30,
"timezone": "Asia/Seoul",
"gender": "male"
}'
การตอบกลับ
ใน data จะมีฟิลด์ผังดวง · การวิเคราะห์เดียวกับ API ปฏิทินหมื่นปี แบบชำระเงิน (wonkuk · ohaengBalance · yongshin · daeun · seun …) พร้อมจำนวนครั้งที่เหลือ guestRemaining จันทรคติ (calendar · isLeapMonth) · การปรับตามตำแหน่ง (พิกัด · country) · zaSiRule · birthTimePrecision มีผลเหมือนแบบชำระเงิน และหากเป็นอินพุตจันทรคติจะมี lunarInput แนบมา เนื่องจากใช้ทดลอง จึงไม่มีการแปล lang · glossary และ identity · ohaengDeficient หากไม่รู้จัก timezone จะมี warnings แนบมาเหมือนแบบชำระเงิน
{
"success": true,
"data": {
"wonkuk": {
"year": { "stem": "기", "branch": "사", "stemHanja": "己", "branchHanja": "巳", ... },
"month": { ... }, "day": { ... }, "hour": { ... }
},
"trueSolarTime": null,
"ohaengBalance": { ... },
"yongshin": "...",
...,
"guestRemaining": 4
}
}
เกินโควตา (429)
{
"success": false,
"statusCode": 429,
"code": "GUEST_QUOTA_EXCEEDED",
"message": "게스트 체험 한도(월 5회)를 초과했어요. API 키를 발급받아 사용해주세요.", // "Guest trial limit (5 per month) exceeded. Please get an API key."
"timestamp": "..."
}
รหัสข้อผิดพลาด
| HTTP | รหัส | เมื่อใด |
|---|---|---|
| 429 | GUEST_QUOTA_EXCEEDED | IP เดียวกันเกิน 5 ครั้งในเดือนนี้ (รวมกับผังดวงกำเนิดสำหรับผู้เยี่ยมชม) |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว กรณีนี้ก็หักจำนวนครั้ง 1 ครั้ง |
| 400 | (ไม่มี) | ตรวจเนื้อหาไม่ผ่าน (เหมือนข้อผิดพลาดทั่วไป) |
POST /api/v1/partners/v1/playground/natal-chart
คำนวณผังดวงกำเนิดโดยไม่ต้องยืนยันตัวตน เนื้อหาคำขอเหมือน /natal-chart แบบชำระเงิน และการตอบกลับก็เป็นผังเดียวกันพร้อม guestRemaining ไม่มีย่อหน้าการอ่าน (readings) โควตารวมกับปฏิทินหมื่นปีสำหรับผู้เยี่ยมชม (5 ครั้งต่อ IP ต่อเดือน)
curl -X POST https://api.hrum.ai/api/v1/partners/v1/playground/natal-chart \
-H "Content-Type: application/json" \
-d '{ "birthDate": "1990-05-15", "birthTime": "12:00", "birthLatitude": 37.5665, "birthLongitude": 126.978, "birthTimezoneOffset": 540 }'
{
"success": true,
"data": {
"sun": { ... },
"moon": { ... },
...,
"guestRemaining": 3
}
}
ข้อผิดพลาด: เกินโควตา 429 GUEST_QUOTA_EXCEEDED นอกนั้นเหมือนข้อผิดพลาดทั่วไป
ค่าที่ใช้ได้
ก้านฟ้า (Cheongan)
갑 (Gap), 을 (Eul), 병 (Byeong), 정 (Jeong), 무 (Mu), 기 (Gi), 경 (Gyeong), 신 (Sin), 임 (Im), 계 (Gye)
กิ่งดิน (Jiji)
자 (Ja), 축 (Chuk), 인 (In), 묘 (Myo), 진 (Jin), 사 (Sa), 오 (O), 미 (Mi), 신 (Sin), 유 (Yu), 술 (Sul), 해 (Hae)
ธาตุทั้งห้า (Ohaeng)
목 (ไม้), 화 (ไฟ), 토 (ดิน), 금 (ทอง), 수 (น้ำ)
ค่ารหัสที่ไม่ขึ้นกับภาษา
ฟิลด์ด้านล่าง แม้ส่ง lang ก็ยังออกเป็นค่ารหัสฮันกึลตามเดิม ไม่ใช่ชื่อสำหรับแสดงบนหน้าจอ แต่เป็นค่าสำหรับแยกเงื่อนไข · ค้นหา ชื่อที่จะแสดงให้ใช้ฟิลด์ที่แปลแล้วในการตอบกลับเดียวกัน (primaryLabel · signEn ฯลฯ) หรืออภิธานศัพท์ glossary: true ของปฏิทินหมื่นปี ประเภทของค่าคือก้านฟ้า · กิ่งดิน · ธาตุทั้งห้าข้างต้น และสิบเทพ (비견 · 겁재 · 식신 · 상관 · 편재 · 정재 · 편관 · 정관 · 편인 · 정인)
- ปฏิทินหมื่นปี —
wonkuk.*.stem·branch·ohaeng,stem·branch·ohaengของdaeun[]·seun[], คีย์ของohaengBalance,cheonganDetail.seasonal.monthBranch, คีย์ของyongshinDetail.element_states,byeongyak.primary·tonggwan.primary(รหัสธาตุทั้งห้า — ชื่อที่แสดงคือprimaryLabel), “청” (ใส) · “탁” (ขุ่น) ของjeongtak.verdict(เฉพาะ “판정불가” (ตัดสินไม่ได้) ที่ถูกแปล), คีย์ของglossary - ปฏิทินหมื่นปี
identity· อัตลักษณ์ —saju.{year,month,day,hour}.{cheongan,jiji,ohaeng},stem·branch·ohaeng·ganjiของtimeline(current · daeunChain · years · highlights),gongmang.void_branches[]·gongmang.hits[].jiji,samjae.current_year_branch,season_strength_hint.yongshin_hint.primary[]·secondary[],sinsal_list[].id(เช่นsinsal12_재살), คีย์ของyongshin.element_states,sipsin_map.* - ปฏิทินหมื่นปี
astrology: true—natalChart.bodies[].sign·element(ภาษาอังกฤษคือsignEn) — เขียนเหมือนใน API ผังดวงกำเนิด - ดวงวันนี้ —
summary.day_master(เช่น “계” Gye),summary.ilju(“계미” Gye-mi),summary.today_day_ohaeng,summary.yongshin,omen.color.ohaeng - กราฟดวงชะตา — การอ่านก้าน-กิ่ง · ธาตุทั้งห้า · ชื่อความสัมพันธ์,
chars[].sipsin,natal.level·natal.result(การตัดสินความแข็ง-อ่อน เช่น “약약” (ค่อนข้างอ่อน) · “중화” (สมดุล)),natal.primaryYongshin·natal.shin.*,triples[].element,compatInputs.*(รวมคีย์ของsurfaceElementCounts) - ดวงสมพงษ์ —
saju.personA/B.ilju,dictionary.a/b.id(ilju_경진) ·name_kr,stem·branch·ohaeng·relations[].target·typeของyearFlow.years[].a/b, คีย์ของsaju.full8.personA/B.elementDistribution·sipsinCount·combinedElementBalance.distribution
โทนคำพูด (candor)
t, f (ค่าเริ่มต้น) — ไม่สนตัวพิมพ์เล็ก-ใหญ่ ค่าเดิม blunt ปรับเป็น t และ balanced · gentle ปรับเป็น f ค่าอื่นได้ 400 (โทนคำพูด (ชื่อชั่วคราว))
รหัสข้อผิดพลาด
ทุก API คืนข้อผิดพลาดทั่วไปด้านล่างด้วยวิธีเดียวกัน ตารางข้อผิดพลาดในแต่ละหัวข้อ API ระบุเฉพาะรหัสที่ออกจาก API นั้นเท่านั้น คำขอจะถูกตรวจตามลำดับต่อไปนี้ หากติดที่ขั้นก่อนหน้า ขั้นถัดไปจะไม่ทำงาน
- กฎความปลอดภัย — กรอง User-Agent ที่ถูกบล็อกก่อนถึงเซิร์ฟเวอร์ API (403 เนื้อหาเป็น HTML error 1010) ตอนนี้ยังไม่ได้ตรวจคีย์ API จึงเป็น 403 ไม่ใช่ 401
- เพดานป้องกันบริการ — เพดานต่อนาทีของคำขอทั้งหมดจาก IP เดียวกัน (429 ไม่มี
code) - คีย์ API — ตรวจ
X-Partner-Api-Key(401) - การเปิดฟีเจอร์ — ฟีเจอร์ที่ยังไม่เปิดในบัญชี (404
*_not_enabled) - ข้อจำกัดคำขอ — ข้อจำกัดต่อวินาที · ต่อวันที่ตั้งในคอนโซล (429
RATE_LIMIT_EXCEEDED) - การตรวจเนื้อหา — ชื่อ · ชนิด · ช่วงของฟิลด์ (400)
- ยอดคงเหลือ · การคำนวณ · การเรียก — ยอดคงเหลือไม่พอ (402) ข้อผิดพลาดอินพุตเฉพาะของ API ข้อผิดพลาดของโมเดลภายนอก
ข้อผิดพลาดทั่วไป
| HTTP | รหัส | เมื่อใด | การคิดค่าบริการ |
|---|---|---|---|
| 400 | (ไม่มี) | ตรวจเนื้อหาไม่ผ่าน — ส่งฟิลด์ที่ไม่มีในตาราง หรือชนิด · ช่วงไม่ถูกต้อง message เป็นอาร์เรย์สตริง | ไม่มี |
| 401 | (ไม่มี) | ไม่มี X-Partner-Api-Key คีย์ไม่ถูกต้อง คีย์ที่ยกเลิกแล้ว บัญชีที่ไม่ได้ใช้งาน | ไม่มี |
| 402 | INSUFFICIENT_BALANCE | ยอดเครดิตคงเหลือไม่พอ การตอบกลับแบบสตรีมจะมี code และ status เดียวกันใน event: error | ไม่มี |
| 402 | (ไม่มี) | ยอดคงเหลือไม่พอ ณ ขณะหัก (API ที่ไม่ตรวจยอดคงเหลือก่อนเรียก หรือกรณีที่คำขออื่นใช้ยอดคงเหลือระหว่างการเรียก) message มีจำนวนเงินที่ต้องใช้และยอดคงเหลือ | ไม่มี |
| 403 | (เนื้อหา HTML) | ถูกบล็อกโดยกฎความปลอดภัย (error 1010) — HTTP client ที่ User-Agent เริ่มต้นถูกบล็อก ดูข้อควรระวังเรื่อง User-Agent ใน Quickstart | ไม่มี |
| 404 | *_not_enabled | ฟีเจอร์ที่ยังไม่เปิดในบัญชี (เช่น ziwei_not_enabled, dream_not_enabled) | ไม่มี |
| 404 | (ไม่มี) | เส้นทางที่ไม่มีอยู่ message ในเนื้อหามีเพียง "Not Found" | ไม่มี |
| 429 | (ไม่มี) | เกินเพดานป้องกันบริการ (300 ครั้งต่อนาทีต่อคีย์ API ฯลฯ) ไม่มี Retry-After — ลองใหม่ภายใน 1 นาที | ไม่มี |
| 429 | RATE_LIMIT_EXCEEDED | เกินข้อจำกัดต่อวินาที · ต่อวันที่ตั้งในคอนโซล จะมี retryAfterSeconds ในเนื้อหาและเฮดเดอร์ Retry-After แนบมา | ไม่มี |
| 500 | (ไม่มี) | ข้อผิดพลาดของเซิร์ฟเวอร์ ยอดที่หักไปแล้วในคำขอนี้จะคืนให้หลังการตอบกลับ | คืนเงิน |
| 503 | SERVICE_DEGRADED | ปัญหาการเชื่อมต่อฐานข้อมูลชั่วคราว Retry-After: 30 — ลองใหม่หลัง 30 วินาที | คืนเงิน |
รูปแบบเนื้อหาการตอบกลับข้อผิดพลาด: {"success": false, "statusCode": 400, "code": "INVALID_LOCATION", "message": "...", "timestamp": "..."} — code แนบมาเฉพาะเมื่อมี ให้แยกเงื่อนไขด้วย statusCode และ code และอย่าพึ่งพาข้อความใน message
// 401 — key missing or invalid
{ "success": false, "statusCode": 401, "message": "Invalid or missing API key", "error": "Unauthorized", "timestamp": "2026-10-12T03:00:00.000Z" }
// 400 — body validation failed (message is an array)
{ "success": false, "statusCode": 400, "message": ["property foo should not exist", "month must not be greater than 12"], "error": "Bad Request", "timestamp": "2026-10-12T03:00:00.000Z" }
// 404 — feature not enabled for the account (message: "This feature is not available yet")
{ "success": false, "statusCode": 404, "code": "ziwei_not_enabled", "message": "아직 열리지 않은 기능입니다", "timestamp": "2026-10-12T03:00:00.000Z" }
// 429 — request limit set in the console (message: "Per-second request limit exceeded. You can adjust it in console > API keys > Request limits.")
{ "success": false, "statusCode": 429, "code": "RATE_LIMIT_EXCEEDED", "message": "초당 요청 제한을 초과했어요. 콘솔 > API 키 > 요청 제한에서 조정할 수 있어요.", "retryAfterSeconds": 1, "timestamp": "2026-10-12T03:00:00.000Z" }
รหัสเฉพาะของ API ที่พบบ่อย: 422 อินพุตที่ประมวลผลไม่ได้ (PROMPT_TOO_LONG, EXTRACTION_FAILED) 503 ใช้งานไม่ได้ชั่วคราว (เช่น ดึงย่อหน้าการอ่านไม่ได้ ไม่คิดค่าบริการ) 504 โมเดลภายนอกหมดเวลา โควตาทดลองใช้แบบผู้เยี่ยมชมคือ 429 GUEST_QUOTA_EXCEEDED
คำเตือนในการตอบกลับ (warnings)
เมื่อคำขอสำเร็จแต่ไม่รู้จักอินพุตบางส่วนจึงคำนวณด้วยค่าเริ่มต้น การตอบกลับที่สำเร็จจะมีอาร์เรย์ warnings แนบท้ายสุดในระดับบนสุดของ data รหัสสถานะยังเป็น 200 และราคาเท่าเดิม หากไม่มีคำเตือนจะไม่มีคีย์ warnings เลย — การตอบกลับเหมือนเดิมทุกอย่าง แต่ละรายการมีเพียง {"code", "field"} และไม่ส่งค่าที่ส่งมา (ข้อมูลการเกิด) กลับไป หากปัญหาเดียวกันอยู่ในหลายฟิลด์ จะมีหนึ่งรายการต่อฟิลด์
| รหัส | ความหมาย | ฟิลด์ที่เกิด |
|---|---|---|
UNKNOWN_TIMEZONE | ไม่รู้จักชื่อเขตเวลา จึงคำนวณด้วยเขตเวลาเริ่มต้น ตรวจว่าพิมพ์ผิดหรือไม่ (เช่น Asia/Seol) หากละไว้หรือเป็นค่าว่างจะไม่เตือน | timezone ของ ปฏิทินหมื่นปี · อัตลักษณ์ซาจู · เปรียบเทียบซาจู ↔ MBTI · ดวงวันนี้ · ดวงชะตาตลอดชีวิต · ปฏิทินหมื่นปีสำหรับผู้เยี่ยมชม, birth.timezone ของ การตีความ KB, personABirthTimezone · personBBirthTimezone ของ ดวงสมพงษ์ |
// 200 — calculated with the default time zone, only a warning is added
{ "success": true, "data": { "wonkuk": { ... }, ..., "warnings": [ { "code": "UNKNOWN_TIMEZONE", "field": "timezone" } ] } }
ข้อจำกัดอัตราการเรียก (Rate Limit)
มีเพดานป้องกันบริการเสมอ: 300 ครั้งต่อนาทีต่อคีย์ API (คำขอด้วยคีย์ทั้งหมดจาก IP เดียวกันคือ 3,000 ครั้งต่อนาที) หากเกินจะคืน 429 และในกรณีนี้การตอบกลับไม่มี code และ Retry-After — ลองใหม่ในภายหลัง (ภายใน 1 นาที) ข้อจำกัดที่ต่ำกว่านี้ พาร์ทเนอร์กำหนดเอง — หากตั้ง คำขอต่อวินาที และ คำขอต่อวัน (ตาม KST) ที่คอนโซล คีย์ API > ข้อจำกัดคำขอ จะปกป้องยอดคงเหลือจากคีย์รั่วไหลหรือลูปไม่สิ้นสุดได้ หากเว้นว่างไว้จะใช้เพียงเพดานป้องกันบริการข้างต้น
- หากตั้งข้อจำกัด การตอบกลับจะมีเฮดเดอร์
X-RateLimit-Limit-Second/X-RateLimit-Remaining-Second/X-RateLimit-Limit-Day/X-RateLimit-Remaining-Dayแนบมา - หากเกินข้อจำกัดที่พาร์ทเนอร์ตั้ง จะได้
429+{"code":"RATE_LIMIT_EXCEEDED","retryAfterSeconds":N}และเฮดเดอร์Retry-Afterคำขอที่ถูกบล็อกไม่คิดค่าบริการ - ผู้เยี่ยมชม (ไม่มีคีย์) กำหนดตายตัวเป็นทดสอบฟรี 5 ครั้งต่อเดือน
การคิดค่าบริการ
การเรียก API ทุกครั้งหักจากเครดิต สมาชิกใหม่จะได้รับเครดิตฟรี ₩1,000 (หากติดเงื่อนไขป้องกันการสมัครโดยมิชอบ การให้เครดิตอาจถูกระงับไว้ก่อน) ผู้เยี่ยมชมทดสอบได้ฟรีสูงสุด 5 ครั้งต่อเดือน
| API | ราคา |
|---|---|
| manseryeok (ปฏิทินหมื่นปี) | ₩50/ครั้ง |
| compat (ดวงสมพงษ์) | ₩20/ครั้ง |
| lifetime (ดวงชะตาตลอดชีวิต) | ทั้งหมด ₩100/ครั้ง · 1 หัวข้อ ₩20/ครั้ง · ชั้นราศี · จื่อเวยโต่วซู่ +₩20/ชั้น |
| ziwei-chart (ผังดวงจื่อเวยโต่วซู่) | ₩50/ครั้ง · readings: true +₩20 (รวม ₩70) |
| identity (อัตลักษณ์ซาจู เอนด์พอยต์เดิม) | ₩10/ครั้ง — การเชื่อมต่อใหม่ใช้ฟิลด์ identity ของปฏิทินหมื่นปี (ไม่มีค่าบริการเพิ่ม) |
| saju-mbti (เปรียบเทียบซาจู ↔ MBTI) | ₩10/ครั้ง (ราคาเดียวกับอัตลักษณ์ซาจู) |
| today (ดวงวันนี้) | ₩10/ครั้ง |
| dream (ทำนายฝัน) | ₩30/ครั้ง (หากไม่มีผลลัพธ์ ₩0) |
| natal-chart (ผังดวงกำเนิด) | ₩20/ครั้ง · readings: true ₩40/ครั้ง |
| personality-type (ประเภทบุคลิกภาพ) - ฟรี | ₩0 (ฟรี) |
| personality-type (ประเภทบุคลิกภาพ) - พรีเมียม | ₩10/ครั้ง |
| reading (AI อ่านดวงซาจู) | ตามโทเค็น (แตกต่างกันตามจำนวนโทเค็นที่ใช้) |
| image (รูปภาพซาจู) | ₩200/รูป |
| image_generation (สร้างรูปภาพ · ขายต่อโมเดล) | ราคาคงที่ต่อรูปตามโมเดล · ความละเอียด · คุณภาพ — ตารางราคา |
ทดสอบแบบผู้เยี่ยมชม
- เอนด์พอยต์ผู้เยี่ยมชมของปฏิทินหมื่นปี · ผังดวงกำเนิด: รวมกันฟรี 5 ครั้งต่อเดือน (จำกัดตาม IP)
- ทดสอบได้ใน Playground โดยไม่ต้องเข้าสู่ระบบ
- จำนวนครั้งที่เหลือรวมอยู่ในการตอบกลับ (guestRemaining)
Idempotency
ทุกคำขอที่สำเร็จจะคิดค่าบริการแยกกัน หากส่งคำขอเดิมซ้ำ จะคำนวณ · สร้างใหม่และคิดค่าบริการอีกครั้ง การลองใหม่ซ้ำซ้อนหรือการนำอินพุตเดิมกลับมาใช้ จึงให้ไคลเอนต์เก็บการตอบกลับไว้แล้วจัดการเอง (เช่น แคชที่ใช้แฮชของคำขอเป็นคีย์)
เฮดเดอร์ X-Idempotency-Key (สูงสุด 128 ตัวอักษร — หากยาวกว่านั้นจะบันทึกเพียง 128 ตัวแรก) ยังรับได้ แต่ไม่ได้ป้องกันการคิดค่าบริการ คีย์ที่ส่งจะถูกบันทึกใน idempotencyKey ของบันทึกการใช้งานตามเดิม ใช้เทียบได้ว่าคำขอใดถูกประมวลผลด้วยการเรียกใด กับ ID คำสั่งซื้อ · งานฝั่งพาร์ทเนอร์
ข้อยกเว้น: การอ่านโหงวเฮ้ง · ลายมือ หากส่งคีย์เดียวกัน · เนื้อหาเดียวกันซ้ำภายใน 24 ชั่วโมง จะคืนผลครั้งแรกและไม่คิดค่าบริการใหม่ (การลองใหม่และการส่งซ้ำ)
ข้อยกเว้น: ศาสตร์ชื่อ หากส่งคีย์เดียวกัน · เนื้อหาเดียวกันซ้ำภายใน 24 ชั่วโมง จะคืนผลครั้งแรกและไม่คิดค่าบริการใหม่ (การลองใหม่และการส่งซ้ำ)
ฝ่ายสนับสนุน
หากติดขัดระหว่างการเชื่อมต่อ หรือการตอบกลับไม่ตรงกับเอกสาร โปรดแจ้งให้เราทราบ
| เรื่องที่ติดต่อ | ช่องทางติดต่อ |
|---|---|
| สนับสนุนด้านเทคนิค · แจ้งเหตุขัดข้อง · ความร่วมมือ | contact@float.do |
เมื่อติดต่อ หากส่งข้อมูลด้านล่างมาด้วยจะตรวจสอบได้เร็วขึ้น
- เอนด์พอยต์ที่เรียกและเวลา (รวมเขตเวลา)
- 12 ตัวแรกของคีย์ API (รวม
float_live_ห้ามส่งคีย์เต็มเด็ดขาด) - รหัสสถานะ HTTP และเนื้อหาของการตอบกลับที่ได้รับ
เรื่องเกี่ยวกับข้อกำหนดและการจัดการข้อมูลส่วนบุคคล โปรดดูข้อกำหนดการใช้งาน (ภาษาเกาหลี)และนโยบายความเป็นส่วนตัว (ภาษาเกาหลี)