คู่มือ API

หากอยากรู้ว่าสแตก API นี้ทำงานอย่างไรในบริการจริง — ลองใช้การวิเคราะห์ซาจูและการสนทนากับ AI ด้วยตัวเองได้ที่ INTA แอป AI ซาจูที่ขับเคลื่อนด้วยเอนจินเดียวกัน INTA คือข้อมูลอ้างอิงที่มีชีวิตของ API นี้ การตอบกลับด้วยเสียง AI (TTS) ของ INTA ก็ขับเคลื่อนด้วยสแตกเดียวกัน — API เสียงจะเปิดให้ใช้ในภายหลัง

Quickstart

HRUM ให้บริการ AI ที่จดจำได้ การวิเคราะห์ซาจู และการขายต่อ LLM ทำตาม 3 ขั้นตอนต่อไปนี้:

ที่อยู่หลักคือ https://api.hrum.ai (API) · https://console.hrum.ai (คอนโซล) ที่อยู่เดิม api.float.do · console.float.do · api.inta.do ยังใช้งานได้ตามเดิม หากเชื่อมต่อไว้แล้วก็ไม่ต้องเปลี่ยน

  1. ออกคีย์ API - สมัครสมาชิกคอนโซลแล้วออกคีย์ที่หน้า คีย์ API (คีย์จะแสดงเพียงครั้งเดียวทันทีหลังออก) ขั้นตอนตั้งแต่สมัครสมาชิกจนถึงการจัดการข้อผิดพลาดสรุปไว้ใน คู่มือเริ่มต้นใช้งานสำหรับนักพัฒนา
  2. ส่งคำขอ - ส่งคำขอ POST ตามตัวอย่างด้านล่าง
  3. จัดการการตอบกลับ - ดึงข้อมูลซาจูจากการตอบกลับ 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

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_FLAGGED400ถูกบล็อกโดยการกลั่นกรองเนื้อหา (ridm: system+user, ขายต่อ: ข้อความ user)
INSUFFICIENT_BALANCE402ยอดคงเหลือไม่พอ (จองขาออกทั้งหมดที่ขอไว้ล่วงหน้าเพื่อตรวจสอบ)
MODEL_NOT_FOUND400โมเดลที่ไม่ได้ตั้งค่า
INVALID_TOOLS / TOOLS_UNSUPPORTED_FOR_MODEL400ฟิลด์ที่เกี่ยวกับ tools ไม่สอดคล้องกัน / ขอเรียกเครื่องมือกับโมเดล Claude
FILE_NOT_FOUND400fileIds มีไฟล์ที่ไม่มีอยู่ (หรือไฟล์ของพาร์ทเนอร์อื่น)
FEATURE_DISABLED403ใช้ตัวเลือกนั้นในบัญชีที่ปิดฟีเจอร์ youtube · files · emotion
RATE_LIMITEDHTTP 400, เนื้อหา status 429ต้นทางจำกัดความเร็ว หรือเกินเพดานการใช้จ่ายรายวันของการขายต่อ (ค่าเริ่มต้นต่อพาร์ทเนอร์ ₩100,000/วัน)
UPSTREAM_TIMEOUTHTTP 400, เนื้อหา status 504ต้นทางตอบกลับเกินเวลา (60 วินาที)
UPSTREAM_INVALID_REQUEST400โมเดลต้นทางปฏิเสธคำขอ (ต้นทาง 400 · 422)
INVALID_RESPONSE_FORMAT400ใช้ response_format: json_object แต่ในข้อความไม่มีคำว่า "json" (ตระกูล OpenAI)
REPORT_ONLY_MODEL400ระบุ ridm/saju-report — ใช้ได้เฉพาะ API รายงานซาจู
(ไม่มี)400ไม่มี user ในโมเดล ridm/* · systemPrompt เกิน 8,000 ตัวอักษร · คำนำหน้าโมเดลที่ไม่รองรับ
provider_not_configured503ตอนนี้โมเดล Claude ไม่ได้เชื่อมต่ออยู่

ข้อควรระวัง

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 นี้ไม่มีรหัสข้อผิดพลาดเฉพาะ — มีเพียงข้อผิดพลาดทั่วไป

เพดานและข้อจำกัด

LLM API (ขายต่อ)

ขายต่อโมเดล LLM ต้นฉบับ เช่น openai/*, google/* (ไม่มีหน่วยความจำ ตอบกลับตามต้นฉบับ) ในคำขอของโมเดลขายต่อ user, systemPrompt, recallCount, memoryCap, summaryEvery, emotion, candor จะถูกละเว้น (คำสั่งระบบให้ใส่เป็น {"role":"system"} ใน messages) และการตอบกลับจะไม่มีฟิลด์หน่วยความจำ (recalledMemories ฯลฯ) ราคา = ต้นทุน × อัตราแลกเปลี่ยน × 1.10

โมเดลที่ให้บริการ (รายการเดียวกับ GET /api/v1/partners/v1/models)

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) จึงคืน 400 TOOLS_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ข้อความการตีความ
sajuSourcecomputed (คำนวณจาก birth) | provided (ใช้ saju ที่ป้อน)
sajuMismatchคำเตือนเมื่อส่ง birth และ saju มาพร้อมกันแต่เสาไม่ตรงกัน ({pillars, computed, note}) กรณีอื่นเป็น null/ไม่มี
toolsUsedเครื่องมือที่ทำงานจริง (เช่น ["youtube"])
toolsSkippedเครื่องมือที่ขอแต่ถูกข้าม [{tool, reason}], reason: unavailable | cap_exceeded | error | auto_rejected
filesUsedID เอกสารที่ถูกแทรก (เมื่อใช้ 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 รหัส
400MISSING_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 ตัวเดียวแยก)
402INSUFFICIENT_BALANCE — ก่อนเรียกจะจองค่าขาออก maxLength × 2 โทเค็น (ระดับ value หรือคำถามที่ไม่ใช่ภาษาเกาหลี +4,000) ไว้ล่วงหน้า จึงอาจถูกปฏิเสธได้แม้ยอดเรียกเก็บจริงจะน้อยกว่า
403FEATURE_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

ตัวอย่างคำขอ (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เรียกอะไรอินพุตที่ต้องใช้ค่าบริการ
sajuAI ซาจู (เฉพาะซาจู ไม่มีรายการอื่น)birth หรือ sajuราคาโทเค็นเท่านั้น (ไม่มีค่าบริการคงที่)
ziweiAI จื่อเวยโต่วซู่birth + เวลาเกิด (hour)ราคาโทเค็น + ราคา 1 ครั้งของ /ziwei-chart
astroAI โหราศาสตร์ตะวันตกbirth (ไม่มีเวลาก็ได้)ราคาโทเค็น + ₩20 (ค่าบริการคงที่ของรายการโหราศาสตร์ตะวันตก)
tarotAI ไพ่ทาโรต์ตัวเลือก tarot — ไม่ต้องใช้ birthราคาโทเค็น + ราคา 1 ครั้งของ /tarot
dreamAI ทำนายฝันเนื้อหาความฝันใน dream — ไม่ต้องใช้ birthราคาโทเค็น + ราคา 1 ครั้งของ /dream

ตัวอย่างคำขอ — เฉพาะ 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
  }
}

ข้อควรระวัง

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รหัสเมื่อใด
400MISSING_ENDUSER_IDendUserId ว่างหรือมีแต่ช่องว่าง
400MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATEข้อมูลการเกิด · อินพุตซาจูผิดพลาด (เหมือน API การอ่านดวง)
400UNKNOWN_TOOL · INVALID_TOOL_MODE · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUNDtools · fileIds ผิดพลาด เส้นทางนี้รับ tools.emotion · tools.summaryEvery ด้วย
400ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALIDข้อผิดพลาดที่เกี่ยวกับการเรียก AI ตัวเดียวแยก
402INSUFFICIENT_BALANCEจองค่าขาออกล่วงหน้าไม่ได้ (วิธีเดียวกับ API การอ่านดวง)
403FEATURE_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รหัสเมื่อใด
404END_USER_NOT_FOUNDendUserId ที่ไม่เคยเห็น (ใช้ร่วมกันใน 4 เส้นทาง ยกเว้นการเก็บบทสนทนา)
400MISSING_PARAMการค้นหา — ไม่มี endUserId
400MISSING_TAGSการค้นหา — tags ว่าง
400ENDUSER_ID_TOO_LONGการเก็บบทสนทนา — endUserId เกิน 255 ตัวอักษร

ข้อควรระวัง

API รายงานซาจู

ไม่ต้องถาม แค่กดปุ่มครั้งเดียวก็ได้การตีความซาจูทั้งหมดในครั้งเดียว ตั้งแต่ภาพรวม · การเงิน · ความรัก · วัยจร 10 ปี เป็นสินค้าแบบชำระเงินรายชิ้นที่แยกจากแบบสนทนา (reading) ค่าเริ่มต้นคือโมเดลเฉพาะ ridm/saju-report (โมเดลเฉพาะทางด้านรายงานของ RIDM เอง — ด้วยลักษณะของสินค้าแบบครั้งเดียวจึงไม่มีหน่วยความจำ) เพดานการตอบของ API การอ่านดวงคือ 2,000 ตัวอักษร — หากต้องการคำอธิบายยาวกว่านั้น (สูงสุด 12 หัวข้อ ประมาณ 6,000 ตัวอักษร) ให้ใช้ API รายงานนี้

POST /api/v1/partners/v1/reading/report

ใส่วันเดือนปีเกิด (หรือซาจู) แล้วจะคืนรายงานซาจูแบบ Markdown แยกตามหัวข้อ

พารามิเตอร์คำขอ

พารามิเตอร์ ชนิด จำเป็น คำอธิบาย
birthobjectbirth หรือ 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") แนบมา
sajuobjectbirth หรือ saju อย่างใดอย่างหนึ่งป้อนสี่เสาโดยตรง {"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}}
year / month / day / gendernumber / stringไม่บังคับฟิลด์แบบแบน (แบบเก่า สุริยคติ) จะถือเป็น birth เฉพาะเมื่อมีค่าครบทั้งสี่ หากไม่มีทั้ง birth · saju จะได้ 400 MISSING_SUBJECT_INPUT
hour / minutenumberไม่บังคับหากละ hour จะตัดเสายามออกและตีความจาก 3 เสา ปี · เดือน · วัน หากส่ง minute โดยไม่มี hour จะถูกละเว้น
tonestringไม่บังคับwarm (ค่าเริ่มต้น) | casual | formal
candorstringไม่บังคับโทนคำพูด — t | f (ค่าเริ่มต้น) เปลี่ยนเพียงการจัดวาง · ความเข้มของข้อดีและข้อยาก ส่วนโครงสร้างหัวข้อ · ข้อห้ามการยืนยันด้านการแพทย์ · กฎหมาย · การลงทุนยังคงเดิม ไม่คิดค่าบริการ ดู โทนคำพูด (ชื่อชั่วคราว)
personastringไม่บังคับคำสั่งเรื่องสำนวน · ตัวละคร (สูงสุด 2,000 ตัวอักษร — คิดค่าบริการขาเข้าเฉพาะความยาวนี้)
sectionsstring[]ไม่บังคับรายการชื่อหัวข้อ (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)
  }
}

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400MISSING_SUBJECT_INPUTไม่มีทั้ง birth · saju
400INVALID_SAJU_PILLARเสาใน saju ไม่อยู่ในวงรอบ 60 คู่ (หกสิบกะจื่อ)
400INVALID_LUNAR_DATEวันที่ตามปฏิทินจันทรคติที่ไม่มีอยู่จริง
402INSUFFICIENT_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"
  }
}

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400INVALID_YOUTUBE_URLหา ID วิดีโอใน URL ไม่พบ
400TRANSCRIPT_UNAVAILABLEวิดีโอที่ไม่มีคำบรรยาย (ไม่คิดค่าบริการ)
400LLM_GENERATION_FAILEDสร้างสรุปล้มเหลวหรือได้ผลลัพธ์ว่าง
402INSUFFICIENT_BALANCEจองค่าสรุปล่วงหน้าไม่ได้
403FEATURE_DISABLEDฟีเจอร์ YouTube ถูกปิดในบัญชี

เปิด-ปิดฟีเจอร์

API สรุป YouTube เลือกเปิดใช้ (opt-in) ได้ทั้งระดับบัญชีพาร์ทเนอร์และระดับคำขอ จัดการสถานะเปิดใช้งานทั้งระบบได้ที่ "ตั้งค่าฟีเจอร์" ในคอนโซล และเปิดใช้รายคำขอโดยระบุ youtube:true ระดับบนสุดสำหรับ chat และ tools: { "youtube": true } สำหรับ reading

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 จะแนบมาเฉพาะเมื่อมีไฟล์ที่ระลึกอัตโนมัติ (หากว่างจะละไว้)

ราคาและการคิดค่าบริการ

เปิด-ปิดฟีเจอร์

ฟีเจอร์ประมวลผลเอกสารเปิด/ปิดได้ที่ระดับบัญชีพาร์ทเนอร์ จัดการได้ที่ "ตั้งค่าฟีเจอร์" ในคอนโซล เมื่อปิด คำขอไฟล์ทั้งหมดจะได้การตอบกลับ 403

สถานะการวิเคราะห์และชิ้นข้อมูล

การตอบกลับของ 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 วิเคราะห์ล้มเหลว (การตอบกลับไม่มีสาเหตุที่ล้มเหลว — อัปโหลดใหม่อีกครั้ง)

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400FILE_NOT_PROVIDEDอัปโหลด — ไม่มีส่วน file
400INVALID_FILE_TYPEอัปโหลด — รูปแบบที่ไม่รองรับ
400FILE_TOO_LARGEอัปโหลด — เกิน 10MB (บางกรณีเป็น 413 ที่ไม่มีรหัส)
400END_USER_REQUIREDอัปโหลด — analyze=true แต่ไม่มี endUserId
400(ไม่มี)รายละเอียด · ลบ — :id ไม่ใช่ UUID
402INSUFFICIENT_BALANCEอัปโหลด — จองค่าวิเคราะห์ล่วงหน้าไม่ได้
403FEATURE_DISABLEDฟีเจอร์ประมวลผลเอกสารถูกปิดในบัญชี (ใช้ร่วมกันทั้ง 4 เส้นทาง)
404FILE_NOT_FOUNDรายละเอียด · ลบ — ไฟล์ไม่มีอยู่หรือเป็นไฟล์ของบัญชีอื่น
422EXTRACTION_FAILEDอัปโหลด — ดึงข้อความจากเอกสารไม่ได้

วิเคราะห์สภาวะอารมณ์ (Emotion)

วิเคราะห์สภาวะอารมณ์ของผู้ใช้และ AI โดยอาศัยรอบการสรุปใน Chat API ไม่มีการเรียก LLM แยก และเพิ่มเพียงบล็อกวิเคราะห์อารมณ์ลงในพรอมต์สรุป จึงไม่มีค่าบริการเพิ่ม รองรับเฉพาะโมเดล ridm/*

ภาพรวม

เงื่อนไขการเปิดใช้งาน:

  1. ทั้งระบบ: partner_emotion_enabled ✓
  2. Partner: เปิด "วิเคราะห์สภาวะอารมณ์" ในการตั้งค่าฟีเจอร์ของคอนโซล
  3. Request: ระบุ emotion: true
  4. Model: รองรับเฉพาะตระกูล ridm/*

รอบการสรุป (summaryEvery)

การวิเคราะห์อารมณ์จะทำงานอัตโนมัติทุกรอบการสรุป ปรับรอบได้ด้วยพารามิเตอร์ summaryEvery (ค่าเริ่มต้น: 5 ช่วง: 1–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)

ตัวอย่างการตอบกลับแบบสตรีมมิง (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]

ข้อมูลค่าใช้จ่าย

ข้อควรระวัง

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
  }
}

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
402INSUFFICIENT_BALANCEยอดคงเหลือน้อยกว่าราคารูปภาพ 1 รูป
504IMAGE_UPSTREAM_TIMEOUTไม่ได้รับรูปภาพภายใน 80 วินาที (ไม่คิดค่าบริการ)

API สร้างรูปภาพ (ขายต่อโมเดล)

POST /api/v1/partners/v1/images/generations

เรียกโมเดล GPT-Image · Nano Banana ด้วยคีย์เดียวในรูปแบบเดียวกับ OpenAI Images API ราคาต่อรูปกำหนดไว้ตามโมเดล · ความละเอียด · คุณภาพ และจะหักตามจำนวนเงินในตารางตามเดิม (จำนวนรูปที่สร้าง × ราคาต่อรูป) ค่าโทเค็นขาเข้าของพรอมต์รวมอยู่ในราคาต่อรูปแล้ว ไม่คิดเพิ่มแยก

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
modelstringOopenai/gpt-image-2, openai/gpt-image-1-mini, google/nano-banana-pro, google/nano-banana, fal/nano-banana-pro, fal/nano-banana
promptstringOคำอธิบายรูปภาพที่จะสร้าง (สูงสุด 1,000 ตัวอักษร) หากเกินจะได้ 422 PROMPT_TOO_LONG (ตรวจหลังจองยอดคงเหลือ หากยอดไม่พอจะได้ 402 ก่อน) สตริงว่างจะได้ 400 EMPTY_PROMPT
sizestringGPT-Image: 1024x1024 (ค่าเริ่มต้น) · 1024x1536 (แนวตั้ง) · 1536x1024 (แนวนอน) · auto (โมเดลเลือก — คิดค่าบริการตามราคาขนาดที่แพงที่สุดของคุณภาพนั้น) ค่าเดิม 256x256 · 512x512 จะสร้างและคิดค่าบริการเป็น 1024x1024, 1792x1024 เป็น 1536x1024, 1024x1792 เป็น 1024x1536 ใน Nano Banana ใช้เป็นสัดส่วนเท่านั้น — แนะนำให้ใช้ aspect_ratio
qualitystringเฉพาะ GPT-Image: low · medium (ค่าเริ่มต้น) · high ค่าเดิม standard=medium, hd=high ยังทำงานได้ตามเดิม หากส่ง low/medium/high ให้ Nano Banana จะได้ 400
aspect_ratiostringเฉพาะ Nano Banana: 21:9 · 16:9 · 3:2 · 4:3 · 5:4 · 1:1 (ค่าเริ่มต้น) · 4:5 · 3:4 · 2:3 · 9:16 สัดส่วนไม่มีผลต่อราคา มีลำดับความสำคัญเหนือ size
resolutionstringเฉพาะ Nano Banana: Nano Banana ใช้ได้เฉพาะ 1K ส่วน Nano Banana Pro ใช้ 1K (ค่าเริ่มต้น) · 2K · 4K อนุญาตเฉพาะ K ตัวพิมพ์ใหญ่
nnumberจำนวนรูปที่สร้าง 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": "..."
}

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400MODEL_NOT_FOUNDโมเดลที่ไม่มีในตารางราคา
400INVALID_MODELคำนำหน้าที่ไม่ใช่ openai/ · google/ · fal/
400INVALID_PARAMETERตัวเลือกที่โมเดลไม่รับ (aspect_ratio · resolution ใน GPT-Image, quality ใน Nano Banana, ความละเอียดที่ไม่รองรับ)
400EMPTY_PROMPTพรอมต์มีแต่ช่องว่าง
400INVALID_PROMPTโมเดลต้นทางปฏิเสธพรอมต์
400UPSTREAM_ERRORต้นทางผิดพลาดหรือได้รูปภาพ 0 รูป (ไม่คิดค่าบริการ)
HTTP 400, เนื้อหา status 429RATE_LIMITEDต้นทางจำกัดความเร็ว — ลองใหม่อีกครั้งในภายหลัง
402INSUFFICIENT_BALANCEราคาต่อรูป × n มากกว่ายอดคงเหลือ
422PROMPT_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
succeededresult = การตอบกลับ 200 ที่การเรียกแบบซิงโครนัสจะคืนให้ตามเดิม (data · costWon · requestId)
failederror = เนื้อหาข้อผิดพลาดที่การเรียกแบบซิงโครนัสจะคืนให้ตามเดิม (statusCode · code · message) — ไม่คิดค่าบริการ
HTTPรหัสเมื่อใด
202—คำขอ Prefer: respond-async ไม่เสร็จภายใน 60 วินาที — ดึงข้อมูลด้วย ID งานข้างต้น
404IMAGE_JOB_NOT_FOUNDID งานที่ไม่มีอยู่ · หมดอายุ · ของพาร์ทเนอร์อื่น
429IMAGE_JOB_POLL_RATE_LIMITEDดึงข้อมูลซ้ำด้วยคีย์ API เดียวกันภายใน 2 วินาที — ลองหลัง Retry-After วินาที
error.statusCode 504IMAGE_UPSTREAM_TIMEOUTไม่ได้รับรูปภาพภายใน 240 วินาที (ไม่คิดค่าบริการ)
error.statusCode 413IMAGE_JOB_RESULT_TOO_LARGEผลลัพธ์เกิน 16MB (ไม่คิดค่าบริการ)
error.statusCode 503IMAGE_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" รูปแบบผลการปรับดูได้จากตัวอย่างอินพุตจันทรคติในข้อควรระวังด้านล่าง

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400INVALID_LUNAR_DATE · INVALID_LOCATIONวันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว (ไม่คิดค่าบริการ)
402(ไม่มี)ยอดคงเหลือน้อยกว่าค่าเรียก — API นี้ไม่ตรวจยอดคงเหลือก่อนเรียก จึงได้ 402 ที่ไม่มีรหัส

API ดวงชะตาตลอดชีวิต

POST /api/v1/partners/v1/lifetime

คำนวณผังดวงจากวันเดือนปีและเวลาเกิด แล้วรวมย่อหน้าการอ่านดวงของส่วนประกอบที่ตรงกับผัง (เสาวัน · ก้านวันเกิด×กิ่งดินเดือน · ก้านวันเกิด×ความแข็ง-อ่อนของดวง · ก้านวันเกิด×ธาตุช่วย · ธาตุเกิน/ขาดสูงสุด 3 รายการ · กลุ่มสิบเทพที่แรงที่สุด) เป็น 7 หัวข้อ บุคลิกภาพ · การเงิน · อาชีพ · ความรัก · สุขภาพ · ความสัมพันธ์ · คำแนะนำ แล้วคืนให้ เป็นย่อหน้าที่เขียนด้วยทฤษฎีซาจูของ HRUM และอินพุตเดียวกันให้ผลเดียวกันเสมอ การตัดสินผังดวงเหมือนกับ API ปฏิทินหมื่นปี

ครบทั้ง 7 หัวข้อ
1 หัวข้อ (topic)
ชั้นราศี · จื่อเวยโต่วซู่ (layers)

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
year · month · daynumberOปีเกิด (1900-2100) · เดือน · วัน (ค่าเริ่มต้นสุริยคติ หาก calendar: "lunar" เป็นจันทรคติ)
hour · minutenumberเวลาเกิด หากละ hour จะคำนวณด้วยกฎกรณีไม่ทราบเวลาเกิดเดียวกับ API ปฏิทินหมื่นปี (ตาม 3 เสา ปี · เดือน · วัน)
timezonestringOเขตเวลา (เช่น Asia/Seoul) หากเป็นชื่อที่ไม่รู้จัก จะคำนวณด้วยเขตเวลาเริ่มต้นและการตอบกลับจะมี warnings (UNKNOWN_TIMEZONE) แนบมา
genderstringO"male" หรือ "female"
topicstringเมื่อต้องการหัวข้อเดียว: personality, wealth, career, love, health, relationships, advice หากละไว้จะได้ทั้ง 7 หัวข้อ
langstringko (ค่าเริ่มต้น) · en · ja · th
layersstring[]ชั้นการอ่านดวงเพิ่มเติม: "astro" (ราศี — ดวงอาทิตย์ · ดวงจันทร์ · ลัคนา) · "ziwei" (จื่อเวยโต่วซู่ — ดาวหลักของวังชะตา + ดาวหลักของวังตามหัวข้อ) จะต่อท้ายย่อหน้าซาจูของแต่ละหัวข้อตามลำดับ ราศี → จื่อเวยโต่วซู่ หากละไว้หรือเป็น [] การตอบกลับจะเหมือนตอนนี้ทุกอย่าง
calendar · isLeapMonthstring · booleanหากเป็น "lunar" จะรับ year · month · day เป็นจันทรคติแล้วแปลงเป็นสุริยคติเพื่อคำนวณ (ค่าเริ่มต้น "solar") isLeapMonth: true คือเดือนอธิกมาส หากปีนั้นไม่มีเดือนอธิกมาสนั้นจะได้ 400 INVALID_LUNAR_DATE (ตั้งแต่ 2026-10-12) หากส่งเป็นจันทรคติ การตอบกลับจะมี lunarInput (รูปแบบเดียวกับ API ปฏิทินหมื่นปี) แนบมา
birthLatitude · birthLongitudenumberพิกัดสถานที่เกิด (ส่งทั้งสองค่าพร้อมกัน) ย่อหน้าซาจูและ layers ปรับเวลาสุริยะจริงด้วยเกณฑ์เดียวกัน เส้นเมริเดียนมาตรฐานกำหนดจากเวลามาตรฐานของ timezone (ไม่รวมเวลาออมแสง) ลัคนาจะออกมาเมื่อมีทั้งเวลาเกิดและพิกัด
countrystringรหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับด้วยลองจิจูดตัวแทนของประเทศนั้น (ประเทศอื่นไม่มีการปรับ) layers ก็ใช้ประเทศนี้ (หากละไว้จะประมาณจาก lang)
zaSiRulestringเสาวันของยามจื่อ (หลัง 23 นาฬิกา): "traditional" (ค่าเริ่มต้น เสาวันของวันถัดไป) · "yajaSi" (ยามจื่อกลางคืน เสาวันของวันนั้น · หลังปรับตามตำแหน่ง ก้านฟ้าของเสายามช่วง 23 นาฬิกาอิงก้านวันเกิดของวันถัดไป ตั้งแต่ 2026-10-20) ใช้เฉพาะกับย่อหน้าซาจู (จื่อเวยโต่วซู่กำหนดตายตัวให้ตั้งแต่ 23 นาฬิกาเป็นวันถัดไป)
birthTimePrecisionstringexact · 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รหัสเมื่อใด
404lifetime_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
400INVALID_LUNAR_DATE · INVALID_LOCATIONวันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอเมื่อตรวจล่วงหน้าด้วยยอดที่รวมชั้นที่ขอไว้
503lifetime_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 · daynumberOปีเกิด (1900-2100) · เดือน · วัน
hournumberOชั่วโมงเกิด (0-23) จื่อเวยโต่วซู่ตั้งผังดวงไม่ได้หากไม่มีเวลาเกิด — หากละไว้จะได้ 400 birth_time_required
minutenumberนาทีเกิด (0-59) หากละไว้เป็น 0
genderstringO"male" หรือ "female" (กำหนดทิศทางเดินของช่วงใหญ่)
calendarstringsolar (ค่าเริ่มต้น) หรือ lunar
isLeapMonthbooleantrue หากเป็นเดือนอธิกมาสตามจันทรคติ อินพุตสุริยคติจะละเว้น หากปีนั้นไม่มีเดือนอธิกมาสนั้น จะคำนวณเป็นเดือนปกติและ chart.lunarDate.isLeapMonth จะเป็น false
birthTimePrecisionstringexact (ปรับเวลาสุริยะจริง) หรือ approximate (ไม่ปรับ + notes.approximateTimeNote) หากละไว้จะไม่ปรับ
birthLatitude · birthLongitudenumberพิกัดสถานที่เกิด (สำหรับการปรับแบบ exact)
countryCodestringISO 2 ตัวอักษรของประเทศเกิด ตัวพิมพ์ใหญ่เท่านั้น (เช่น KR — kr ได้ 400) เมื่อไม่มีพิกัดจะปรับด้วยลองจิจูดตัวแทน
birthTimezoneOffsetnumberค่าชดเชย UTC ของเวลาเกิด (นาที 540 = KST)
referenceDatestringวันอ้างอิงของช่วงใหญ่ · ปีจร YYYY-MM-DD (ค่าเริ่มต้น: วันนี้ ตามเวลาเกาหลี)
langstringko (ค่าเริ่มต้น) · en · ja · th
timezonestringเพื่อความเข้ากันได้กับ API ปฏิทินหมื่นปี (ไม่ได้ใช้ในการคำนวณ แม้เป็นชื่อที่ไม่รู้จักก็ไม่มีคำเตือน)
readingsbooleanหากเป็น 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 ของย่อหน้านั้นจะเป็น ko missingSections คือจำนวนย่อหน้าที่ถูกตัดเพราะยังไม่มีประโยคการอ่านดวง (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 (บัญชียังไม่เปิดฟีเจอร์) · 404 ziwei_readings_not_enabled (ยังไม่เปิดย่อหน้าการอ่านดวง) · 503 ziwei_readings_unavailable (ดึงย่อหน้าการอ่านดวงไม่ได้)

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404ziwei_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
404ziwei_readings_not_enabledreadings: true แต่ยังไม่เปิดย่อหน้าการอ่านดวง
400invalid_birth_dateวันที่สุริยคติที่ไม่มีอยู่จริง หรืออยู่นอกช่วงวัน · เดือนอธิกมาสตามจันทรคติ
400birth_time_requiredไม่มี hour — จะได้ partial มาด้วยเหมือนตัวอย่างด้านบน
400reference_date_before_birthreferenceDate มาก่อนวันเกิด
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอ
503ziwei_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-16 ohaeng เป็น null หมายถึงไม่มีเสายาม) จำนวนธาตุทั้งห้าไม่รวมเสายาม
  • ราคา: /identity เดิม ₩10/ครั้ง (เฉพาะเมื่อเปิดในบัญชี หากไม่เปิดจะได้ 404 identity_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รหัสเมื่อใด
404identity_not_enabledบัญชียังไม่ได้เปิด
400INVALID_LUNAR_DATE · INVALID_LOCATIONวันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว
402INSUFFICIENT_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 ตำแหน่งขึ้นไป) มาบวกแยกตามตัวอักษรในแต่ละแกน แล้วเลือกฝั่งที่มากกว่า หากเท่ากันหรือไม่มีกฎที่ตรงจะเป็น balanced ID กฎที่ตรงอยู่ใน 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 หรือมีคีย์ที่ไม่รู้จัก
400INVALID_LUNAR_DATE · INVALID_LOCATIONวันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอ
404saju_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 แนบมาเหมือนปฏิทินหมื่นปี เพิ่มเติม:

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
datestringวันที่ต้องการดู YYYY-MM-DD (1900-2100) หากละไว้คือวันนี้ตามเวลาเกาหลี
temperatureCnumberอุณหภูมิปัจจุบัน (℃, −40~50) หากส่งมา การตอบกลับจะมี fashion (การแต่งกายช่วงเช้า · กลางวัน · เย็น) หากละไว้จะไม่มี fashion (ไม่ประมาณเอง)
weatherstringสภาพอากาศ: clear · cloudy · rain · snow · storm
humiditynumberความชื้นสัมพัทธ์ (%, 0~100) ต้องส่งครบทั้งสามค่า temperatureC · weather · humidity จึงจะมี fashion.mood (ความเห็นเรื่องอากาศหนึ่งบรรทัดตามช่วงเวลา)
mbtiBehaviorbooleanหากเป็น 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: เฉพาะเมื่อส่ง temperatureC fashion.mood เฉพาะเมื่อส่งครบ temperatureC · weather · humidity mbtiBehavior: เฉพาะเมื่อ 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รหัสเมื่อใด
404today_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
400INVALID_LUNAR_DATE · INVALID_LOCATIONวันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอ

API ทำนายฝัน

POST /api/v1/partners/v1/dream

ค้นหาคำสัญลักษณ์ (เช่น ทะเล ปลา) จากเรื่องความฝันที่ผู้ใช้ปลายทางเล่า แล้วคืนตามลำดับความโดดเด่น คำเหล่านี้ค้นจากคลังคำสัญลักษณ์ความฝันที่ HRUM สร้างขึ้นเอง (คำนามในชีวิตประจำวันกว่า 1,000 คำ พร้อมคำพ้องความหมาย · รูปผันคำ · ภาษาพูด) คลังคำมีแต่คำ ไม่มีความหมายการทำนายหรือการตัดสินดีร้าย ทุกคำที่คืนมาคือคำที่คำนั้นหรือคำพ้องความหมาย · รูปผันคำปรากฏจริงในเนื้อหาความฝัน

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
dreamstring✓เรื่องความฝัน (สูงสุด 1,000 ตัวอักษร)
feelingstringอารมณ์ที่รู้สึกในความฝัน (สูงสุด 300 ตัวอักษร เช่น "무섭고 답답했어요" — "ทั้งกลัวทั้งอึดอัด") รวมกับเนื้อหาความฝันแล้วดึงแท็ก (ใช้ความยาวรวมได้ถึง 1,000 ตัวอักษร)
langstringภาษาของการตอบกลับ ปัจจุบันรองรับเฉพาะ ko (พจนานุกรมเป็นภาษาเกาหลีเท่านั้น) ค่าอื่นได้ 400
includeNegativeboolean จะรวมบันทึกการตัดสินในทางร้าย (ความตาย · โรค · การสูญเสีย ฯลฯ) ในหลักฐานจากตำราโบราณหรือไม่ ค่าเริ่มต้น 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 · neutral negative (บันทึกเรื่องความตาย · โรค · การสูญเสีย ฯลฯ) จะรวมเฉพาะเมื่อ includeNegative: true
  • caveatRuleIds: กฎข้อควรระวังที่เกี่ยวกับกฎนั้น (เช่น บันทึกเรื่องความตาย · โรคภัยคือ R-DREAM-CAVEAT-002)
  • หากไม่มีกฎที่ตรงจะเป็นอาร์เรย์ว่าง การเรียกที่ไม่ถูกคิดค่าบริการ (เช่น การเรียกที่ได้ items: [] เป็น ₩0) จะไม่มีแนบมา

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404dream_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
402INSUFFICIENT_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, modelVersionstring✓โมเดลที่สร้างพิกัด หากอยู่นอกรายการที่อนุญาตจะได้ 400 MEASURE_MODEL_UNSUPPORTED / MEASURE_MODEL_VERSION_MISMATCH ปัจจุบัน: face_landmarker · float16/[email protected]
normalizationstring✓face-norm-1
landmarksnumber[][]✓[x, y] หรือ [x, y, z] จำนวน 478 จุดพอดี (ค่าที่หารด้วยความกว้าง · ความสูงของภาพ −0.02~1.02)
imageWidth, imageHeightnumber✓ขนาดเป็นพิกเซล
hairline[number, number]จุดแนวไรผมกลางใบหน้าหนึ่งจุด เซิร์ฟเวอร์ไม่ประมาณเอง — หากไม่มี คีย์ที่เกี่ยวกับส่วนบนของใบหน้า (upper court) จะเป็น null (สาเหตุ hairline_missing) แนะนำให้ผู้ใช้แตะจุดเริ่มของเส้นผมเหนือหน้าผากเป็นอินพุต (โมเดลแบ่งส่วนเส้นผมใช้เพื่ออ้างอิงเท่านั้น)
qualityobjectyawDeg · pitchDeg · rollDeg · blendshapes (ชื่อสัมประสิทธิ์ MediaPipe→คะแนน) ต้องส่งมาจึงจะตรวจคุณภาพได้
includeNegativebooleanจะรวมบันทึกการตัดสินในทางร้าย (polarity negative) หรือไม่ ค่าเริ่มต้น false (ชื่อ · ความหมายเดียวกับทำนายฝัน)

POST /api/v1/partners/v1/palm-measure

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
modelName, modelVersionstring✓ปัจจุบัน: hand_landmarker · float16/[email protected]
normalizationstring✓palm-norm-1
landmarksnumber[][]✓21 จุดพอดี
imageWidth, imageHeightnumber✓ขนาดเป็นพิกเซล
handednessstring✓left | right — มือจริงของผู้ถูกถ่าย (ให้ผู้ใช้เลือก)
mirroredbooleanหากเป็นภาพกลับซ้าย-ขวา (พรีวิวเซลฟี) ให้เป็น true
creasesobject[]โพลีไลน์ของเส้นลายมือ (สูงสุด 64 เส้น เส้นละ 2~512 จุด) รายการ: points (✓), label (life · head · heart · fate · sun · mercury · simian · unknown), kind (segment | branch), autoLabel หากไม่มี คีย์ที่เกี่ยวกับเส้นจะเป็น null (creases_missing)
autoLabelbooleanตั้งชื่อเส้นที่ไม่มีชื่อทั้งหมดด้วยฮิวริสติกกลางของเซิร์ฟเวอร์ หากต้องการใช้กับเส้นเดียว ให้ใช้ autoLabel ของรายการนั้น label ที่ตั้งเองมีลำดับความสำคัญสูงกว่าเสมอ
includeNegativebooleanเหมือนใบหน้า ค่าเริ่มต้น 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 เป็นบันทึกว่าต้นฉบับเขียนไว้เช่นนั้น ให้สื่อสารกับผู้ใช้ว่า "มีบันทึกว่ามีแนวโน้มเช่นนี้ + อาจรับมือได้แบบนี้" และอย่าเปลี่ยนเป็นคำที่ดูถูกคนหรือตีตราบุคลิกภาพ

รหัสข้อผิดพลาด

HTTPcodeความหมาย
400MEASURE_MODEL_UNSUPPORTEDmodelName ไม่อยู่ในรายการที่อนุญาต
400MEASURE_MODEL_VERSION_MISMATCHmodelVersion ไม่อยู่ในรายการที่อนุญาต (ปัจจุบันเฉพาะ float16/[email protected])
400MEASURE_NORMALIZATION_MISMATCHnormalization ไม่ใช่ face-norm-1 / palm-norm-1
400MEASURE_LANDMARK_COUNTจำนวนพิกัดไม่ใช่ใบหน้า 478 / มือ 21
400MEASURE_LANDMARK_SHAPE · MEASURE_COORD_NAN · MEASURE_COORD_RANGE · MEASURE_IMAGE_SIZE · MEASURE_DEGENERATEข้อผิดพลาดของรูปแบบจุด · ตัวเลข · ช่วง (−0.02~1.02) · ขนาดภาพ
400MEASURE_HANDEDNESS · MEASURE_CREASE_LIMIT · MEASURE_CREASE_SHAPE · MEASURE_CREASE_LABELอินพุตมือ · เส้นลายมือผิดพลาด
400MEASURE_QUALITY_POSE · MEASURE_QUALITY_FACE_SIZEหันหน้าเกิน 10° · ใบหน้าเล็กเกินไป — ถ่ายใหม่
400(ข้อผิดพลาดการตรวจสอบ)ส่งฟิลด์ที่ไม่มีในเอกสาร — ส่งเฉพาะฟิลด์ที่อนุญาต
402INSUFFICIENT_BALANCEยอดเครดิตคงเหลือไม่พอ
404face_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

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
imageobjectอย่างใดอย่างหนึ่ง{ data, mimeType } — data คือ base64 ของไบต์รูปถ่าย (ไม่เกิน 8MB หลังถอดรหัส) mimeType คือ image/jpeg · image/png · image/webp รูปแบบจะถูกตรวจซ้ำจากไบต์ (หากไม่ตรงได้ 400)
landmarksobjectอย่างใดอย่างหนึ่งเนื้อหาคำขอของการวัดโหงวเฮ้งตามเดิม (modelName · modelVersion · normalization · landmarks 478 จุด · imageWidth · imageHeight · hairline · quality · includeNegative)
consentobject✓ หากเป็นรูปถ่ายความยินยอมในการประมวลผลรูปถ่าย — ดูอ็อบเจกต์ความยินยอมด้านล่าง
llmbooleanไม่ต้องส่งก็ได้ — รวมคำอธิบายจาก AI เสมอ หากส่ง false จะได้ 400 USE_FACE_MEASURE (การวัดโดยไม่ใช้ AI คือการวัดโหงวเฮ้ง)
langstringรับ ko · en · ja · th แต่ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี (lang ในการตอบกลับ = "ko")
endUserIdstringID ผู้ใช้ปลายทางที่พาร์ทเนอร์ใช้ (สูงสุด 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

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
imageobject✓รูปด้านฝ่ามือหนึ่งรูป รูปแบบ · ขนาดเหมือนโหงวเฮ้ง
consentobject✓อ็อบเจกต์ความยินยอม
creasesobject[]เส้นลายมือที่ผู้ใช้วาดตามบนรูปถ่าย (สูงสุด 16 เส้น) รายการ: line (life · head · heart · fate · sun · mercury · simian · unknown), points ([x, y] 2~256 จุด 0~1 โดยนับจากมุมซ้ายบนของรูป) ใช้เป็นข้อมูลอ้างอิงหลักในการหาตำแหน่งเส้น
langstringเหมือนโหงวเฮ้ง (ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี)
endUserIdstringเหมือนโหงวเฮ้ง

ตัวอย่างคำขอ (ลายมือ เส้นที่วาดตาม)

{
  "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": { "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) รูปหลังมือได้ 400 PALM_NOT_DETECTED สำหรับลายมือ ให้ถ่ายโดยมีฝ่ามือเพียงข้างเดียวในภาพ แม้ปลายนิ้วของอีกมือโผล่มาเพียงเล็กน้อย ก็อาจถูกมองว่าเป็นสองมือและถูกปฏิเสธ
  • โมเดลภายนอก: ส่งไปยัง OpenAI (สหรัฐอเมริกา) ส่งด้วย store: false OpenAI ไม่ใช้อินพุต 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 · chin key ของลายมือ: hand_shape · fingers · life_line · head_line · heart_line · fate_line · sun_line · mounts label มาเป็นภาษาเกาหลี
  • โหงวเฮ้งที่ส่งเป็น 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 (หรือข้อความที่มีความหมายเดียวกัน) บนหน้าจอผู้ใช้ด้วย

รหัสข้อผิดพลาด

HTTPcodeความหมาย
400READING_INPUT_ONE_OFโหงวเฮ้ง: ไม่ได้ส่ง image หรือ landmarks อย่างใดอย่างหนึ่งพอดี
400IMAGE_REQUIREDลายมือ: ไม่มี image
400CONSENT_REQUIREDเป็นรูปถ่ายแต่ไม่มี consent หรือค่าไม่ถูกต้อง
400IMAGE_INVALID · IMAGE_FORMAT_UNSUPPORTEDอ่านรูปไม่ได้ · mimeType ต่างจากรูปแบบจริง · ไม่ใช่ JPEG · PNG · WebP (รวม WebP แบบเคลื่อนไหว)
413IMAGE_TOO_LARGEรูปเกิน 8MB · เกิน 8192px หรือ 16.8 เมกะพิกเซล · ด้านยาวของ WebP เกิน 1600px
400IMAGE_NOT_ALLOWEDดูเหมือนผู้เยาว์ · หลายใบหน้า / สองมือขึ้นไป · ไม่ใช่รูปใบหน้า · ฝ่ามือ
400FACE_NOT_DETECTED · PALM_NOT_DETECTEDหาใบหน้า / ฝ่ามือไม่พบ (รูปหลังมือคือ PALM_NOT_DETECTED)
400USE_FACE_MEASUREllm: false กับ landmarks ของโหงวเฮ้ง — การวัดโดยไม่ใช้ AI คือ API วัดโหงวเฮ้ง
400MEASURE_LOW_QUALITYเบลอ · มืด · ถูกบัง · เล็กเกินไป · เอียง — เหตุผลอยู่ใน quality ของการตอบกลับ แนะนำให้ถ่ายใหม่
400CREASE_INVALIDจุดของเส้นลายมือน้อยกว่า 2 จุดหรืออยู่นอก 0~1
400MEASURE_*อินพุต landmarks ผิดพลาด (รหัสเดียวกับการวัดโหงวเฮ้ง)
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอ — ตรวจก่อนเรียกโมเดลภายนอก
404face_reading_not_enabled · palm_reading_not_enabledฟีเจอร์ที่ยังไม่เปิด
409IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESSใช้ X-Idempotency-Key เดียวกันกับเนื้อหาอื่น · คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่ (ดูการลองใหม่และการส่งซ้ำด้านล่าง)
429FILTERED_QUOTA_EXCEEDEDรูปที่ถูกกรองวันนี้ถึงเพดานรายวันแล้ว — ดูเพดานรายวันของรูปที่ถูกกรองด้านล่าง
502READING_UNAVAILABLEสร้างคำอ่านไม่ได้ (รวมกรณีเอาต์พุตถูกตัด) — โปรดลองใหม่อีกครั้ง
503IMAGE_BUSYการประมวลผลรูปถ่ายหนาแน่น — โปรดลองใหม่ในภายหลัง
504LLM_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): คำนวณอย่างเดียว ไม่เรียก AI interpretation เป็น null และไม่ต้องมี consent ทั้งสองแบบราคาต่างกัน (ตารางราคา)
  • ประโยคการอ่านตอนนี้มีเฉพาะภาษาเกาหลี แม้ส่ง lang อื่นก็ตอบเป็นภาษาเกาหลี (lang ในการตอบกลับ = "ko")

POST /api/v1/partners/v1/naming

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
name.hangulstring✓ชื่อฮันกึล 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 ตัวอักษร) ธาตุตามความหมายอักษรจะดูจากความหมายนี้เท่านั้น
birthobject{ year, month, day, hour?, minute?, gender?, timezone? } (สุริยคติ) หากส่งมาจะคำนวณธาตุช่วยของซาจูแล้วดูว่าชื่อเติมธาตุนั้นหรือไม่ timezone ค่าเริ่มต้น Asia/Seoul วันเดือนปีเกิดจะไม่ถูกส่งไปยังโมเดลภายนอก
interpretbooleanค่าเริ่มต้น true (อ่านความหมายชื่อ) หากเป็น false จะคำนวณชื่ออย่างเดียว (ไม่ใช้ AI)
echoNamebooleanเพิ่มเมื่อ 2026-10-31 ค่าเริ่มต้น true (เหมือนตอนนี้) หากเป็น false จะไม่เขียนตัวอักษรของชื่อซ้ำที่ใดในการตอบกลับเลย — name เป็น null และ hangul · hanja · meaning ของ deterministic.syllables เป็น null แต่จะมี position (เริ่มจาก 1) แนบมาแทน การแสดงตัวอักษรใน items ก็เปลี่ยนเป็นตำแหน่ง เช่น "첫 글자(목(木))" ("อักษรตัวแรก (ธาตุไม้)") และหากเป็นการอ่านความหมายชื่อ จะไม่ส่งตัวชื่อไปยัง AI (ส่งเฉพาะค่าที่คำนวณและตำแหน่ง)
consentobject✓ หากอ่านความหมายชื่อ{ "version": "name-consent-2026-10", "subject": "end_user" } — version คือเวอร์ชันของข้อความขอความยินยอมที่พาร์ทเนอร์แสดง (1~40 ตัวอักษร) subject คือ end_user · third_party หากไม่มีหรือค่าไม่ถูกต้องจะได้ 400 CONSENT_REQUIRED บันทึกการใช้งานเก็บเพียง version และ subject หาก interpret: false ไม่ต้องใช้
langstringรับ ko · en · ja · th แต่ตอนนี้ตอบเป็นภาษาเกาหลีเท่านั้น
endUserIdstringID ผู้ใช้ปลายทางของพาร์ทเนอร์ (เฉพาะในบันทึกการใช้งาน)
  • จำนวนขีดคำนวณเป็นจำนวนขีดแบบดั้งเดิม (ตามอักษรต้นแบบ) (เช่น 氵 นับเป็น 水 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" }, ...
    ]

รหัสข้อผิดพลาด

HTTPcodeความหมาย
400NAME_INVALIDชื่อฮันกึลไม่ใช่ 2~6 พยางค์ · รูปแบบค่า hanja/strokes/meanings ผิดพลาด
400NAME_HANJA_LENGTHความยาวของ hanja ต่างจากจำนวนพยางค์
400CONSENT_REQUIREDอ่านความหมายชื่อแต่ไม่มี consent หรือค่าไม่ถูกต้อง
400(ข้อผิดพลาดการตรวจสอบ)วันที่ไม่มีอยู่จริง · ฟิลด์ที่ไม่มีในเอกสาร
402INSUFFICIENT_BALANCEยอดคงเหลือไม่พอ
404naming_not_enabledฟีเจอร์ที่ยังไม่เปิด (อ่านความหมายชื่อ · คำนวณชื่อ แยกกัน)
409IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESSใช้ X-Idempotency-Key เดียวกันกับเนื้อหาอื่น · คำขอแรกของคีย์เดียวกันยังประมวลผลอยู่ (ดูการลองใหม่และการส่งซ้ำด้านล่าง)
502READING_UNAVAILABLEสร้างการตีความโดย AI ไม่ได้ — ไม่คิดค่าบริการ (ไม่มีการคิดค่าบริการบางส่วนที่คืนเฉพาะการคำนวณ) โปรดลองใหม่อีกครั้ง
504LLM_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 — ความหมายคือประโยคที่กำหนดไว้ของไพ่ตามเดิม จึงมีวิธีใช้สามแบบ

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
countnumber△จำนวนใบที่จะสุ่ม 1~10 (จำนวนเต็ม) ส่ง count หรือ spread อย่างใดอย่างหนึ่งเท่านั้น หากส่งทั้งสองหรือไม่ส่งเลยจะได้ 400
spreadstring△รูปแบบการวางไพ่ กำหนดจำนวนใบและชื่อตำแหน่งไว้แล้ว: single (ไพ่ประจำวัน 1 ใบ) · past-present-future (อดีต · ปัจจุบัน · อนาคต 3 ใบ) · choice (ทางเลือก: สถานการณ์ปัจจุบัน · อุปสรรค · ผลลัพธ์ 3 ใบ) · celtic-condensed (เซลติกแบบย่อ 5 ใบ) · future-prediction (ทำนายอนาคต 5 ใบ)
reversedbooleanอนุญาตไพ่หัวกลับ (ค่าเริ่มต้น true) หากเป็น false จะเป็นหัวตั้งทั้งหมด
seedstringสตริงสำหรับทำซ้ำ (1~200 ตัวอักษร) seed เดียวกัน + count/spread เดียวกัน + reversed เดียวกัน จะได้ไพ่เดิมเสมอ หากไม่มีจะสุ่มทุกครั้ง (ตัวเลขสุ่มเชิงวิทยาการเข้ารหัส)
questionstringคำถามของผู้ใช้ปลายทาง (สูงสุด 500 ตัวอักษร) ไม่ใช้ในการตีความ แต่คืนในการตอบกลับตามเดิม — เป็นฟิลด์ที่มีไว้เพื่อความสะดวกเมื่อส่งต่อไปยังขั้น LLM ถัดไป
langstringภาษาของชื่อไพ่ · คีย์เวิร์ด · ความหมาย · ชื่อรูปแบบการวางไพ่: 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
  }
}

ราคา

หลักฐานจากต้นฉบับ Waite kb

เมื่อเปิดแล้ว การตอบกลับจะมี kb แนบมา สำหรับไพ่แต่ละใบที่สุ่มได้ จะคืนความหมายหัวตั้ง · หัวกลับของไพ่ใบนั้นจากต้นฉบับ A. E. Waite, The Pictorial Key to the Tarot (1910 สาธารณสมบัติ) พร้อม ID กฎ (R-TAROT-*) และการอ้างอิงต้นฉบับ meaning · keywords ข้างต้นคงเดิม เพิ่มเพียง kb และราคาเท่าเดิม

{
  "method": "celtic-cross",
  "seed": "user-1042:2026-10-11"
}

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404tarot_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
404tarot_kb_not_enabledส่ง method แต่หลักฐานจากต้นฉบับยังไม่เปิด
402INSUFFICIENT_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 (ไม่คิดค่าบริการ)

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404natal_readings_not_enabledreadings: true แต่ยังไม่เปิดย่อหน้าการอ่าน
503natal_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 (อิงเที่ยงวัน)

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
houseSystemsstring[]เลือกจาก placidus · whole_sign · equal · porphyry หากละไว้เป็น ["placidus"] สถานที่เกิดในเขตขั้วโลก (ละติจูดประมาณ 66.56° ขึ้นไป angles.polar) จะคำนวณแบบ Porphyry แทน Placidus และแนบ "fallbackFrom": "placidus" ในผลนั้น (แม้ระบุ Placidus เองก็เช่นกัน)
minorAspectsbooleanรวมเซมิเซ็กซ์ไทล์ (30°) · เซมิสแควร์ (45°) · เซสควิควอดเรต (135°) · ควินคันซ์ (150°) (ผังกำเนิด · ซินแนสทรี) ค่าเริ่มต้น false — เฉพาะ 5 มุมหลัก
orbsstringตารางออร์บของผังกำเนิด · ซินแนสทรี: leo1928 (ค่าเริ่มต้น — กุมและเล็ง อาทิตย์–จันทร์ 12° อาทิตย์/จันทร์–ดาวเคราะห์ 10° ดาวเคราะห์ด้วยกัน 8° สแควร์ · ไตรน์ 8° เซ็กซ์ไทล์ 7° เซมิสแควร์ · เซสควิ 4° เซมิเซ็กซ์ไทล์ · ควินคันซ์ 2°) · heindel1919 (มุมหลักค่าเดียว 6° แบบอนุรักษ์)
nodestringโหนดที่ Nn (โหนดเหนือ) · Sn (โหนดใต้ = โหนดเหนือ + 180°) ในคีย์กฎจะใช้: mean (ค่าเริ่มต้น โหนดเฉลี่ย) · true (โหนดจริง) ใช้กับ node_sign Nn_… · Sn_… ของ features และคีย์กุมโหนด (Mo_Nn_cj · Nn_Asc_cj ฯลฯ) คีย์ MNn_… · TNn_… ออกมาทั้งคู่ไม่ว่าค่านี้จะเป็นอะไร
langstringภาษาของ signName (ชื่อราศี) — ko (ค่าเริ่มต้น) · en · ja · th
timingobjectหากส่งมา จะคำนวณทรานซิต + Secondary Progression แล้วใส่ใน timing ของการตอบกลับ ดูตารางด้านล่าง
partnerobjectอินพุตการเกิดของอีกฝ่าย (ฟิลด์เดียวกับข้างต้น ยกเว้น lang) หากส่งมา จะใส่มุม · ความสัมพันธ์ราศีระหว่างสองคนใน synastry ของการตอบกลับ หากมีเวลาเกิดและพิกัด (birthLatitude · birthLongitude) ของอีกฝ่าย จะคำนวณลัคนา (Asc) · กลางฟ้า (MC) ของอีกฝ่ายแล้วใส่ในมุมไขว้ด้วย

ภายในบล็อก timing:

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
orbDegreesnumberOออร์บ (องศา) ของมุมทรานซิต→กำเนิด และโปรเกรสชัน→กำเนิด 0.5~10 ใช้ค่าเดียวกันกับทุกคู่ดาว (เฉพาะ 5 มุมหลัก)
atstringเวลาที่ต้องการดู YYYY-MM-DD (= 00:00 UTC ของวันนั้น) หรือวันเวลาที่มีค่าชดเชย (2026-10-11T09:00:00+09:00, ...Z) วันเวลาที่ไม่มีค่าชดเชยได้ 400 หากละไว้คือตอนนี้
progressionsbooleanคำนวณ Secondary Progression (ค่าเริ่มต้น true)
yearLengthstringความยาว 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 เลย

ตัวอย่างคำขอ 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
  }
}

ตัวอย่างคำขอ 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
  }
}

ค่าเริ่มต้นและค่าที่ต้องเลือกเอง

สิ่งที่ไม่ได้ให้บริการ

ราคา

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404astrology_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
400at_before_birthtiming.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

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
birthDatestringOYYYY-MM-DD (1900~2100) วันที่ตาม calendar
birthTimestring | nullHH:mm หากไม่มีจะถือว่าไม่ทราบเสายาม — คำนวณตาม 6 อักษร และ hourKnown: false
calendarstringOsolar · lunar (จันทรคติจะแปลงเป็นสุริยคติแล้วคำนวณ)
isLeapMonthbooleanเดือนอธิกมาสตามจันทรคติ (ค่าเริ่มต้น false)
genderstring | nullmale · female หากไม่มีจะไม่มีชั้นวัยจร 10 ปี (daeun: [], daeunIndex: null)
timezonestringรับเฉพาะ Asia/Seoul
birthLatitude · birthLongitudenumberพิกัดสถานที่เกิด (ต้องส่งทั้งสองค่า) ฟิลด์เดียวกัน · กฎเดียวกับ API ปฏิทินหมื่นปี — ปรับเวลาสุริยะจริงด้วยลองจิจูด และกราฟดวงชะตาก็วาดบนผังดวงที่ปรับแล้วซึ่งปฏิทินหมื่นปีคืนให้ หากส่งค่าเดียวจะได้ 400 INVALID_LOCATION หากไม่ส่งจะใช้การจัดการเริ่มต้นของปฏิทินหมื่นปี (ตอนนี้ไม่ปรับ) และแจ้งด้วย assumedLocation
countrystringรหัสประเทศเกิด 2 ตัวอักษร หากส่ง KR · JP · TH โดยไม่มีพิกัด จะปรับด้วยลองจิจูดตัวแทนของประเทศนั้น (เหมือนปฏิทินหมื่นปี)
birthTimePrecisionstringexact · approximate · estimated · unknown ปรับเฉพาะเมื่อเป็น exact (หากส่งตำแหน่ง ค่าเริ่มต้นคือ exact) หากส่งค่าที่ไม่ใช่ exact จะคำนวณโดยไม่ปรับเวลาสุริยะจริง ผู้ที่เกิดในช่วงเวลาออมแสงของเกาหลีจะลบ 1 ชั่วโมงแล้วอ่านเป็นเวลามาตรฐานเหมือนปฏิทินหมื่นปี (2026-10-16)
rangeobjectO{ "fromYear", "toYear" } ช่วงของดวงรายปี (ปีสุริยคติ สูงสุด 101 ปี) แนะนำให้ดึงช่วงปีเกิด ~ ปีเกิด+100 ไว้ครั้งเดียว แล้วตัดใช้บนหน้าจอ
monthsOfYearinteger | nullปีซาจูที่จะคำนวณดวงรายเดือน 12 ช่อง (ตั้งแต่ลี่ชุนของปีนั้นจนถึงก่อนลี่ชุนของปีถัดไป) หากละไว้คือปีซาจูที่ตอนนี้ (เวลาเกาหลี) อยู่ — ช่วง 1 มกราคม~ก่อนลี่ชุนคือปีก่อน หากเป็น null จะไม่มีชั้นดวงรายเดือน (months: [])
langstringko · 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
  }
}

วิธีอ่านฟิลด์

ราคา

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
404saju_flow_not_enabledบัญชียังไม่ได้เปิดฟีเจอร์
400INVALID_DATEรูปแบบ birthDate ผิดพลาดหรือวันที่ไม่มีอยู่จริง
400INVALID_LUNAR_DATEวันที่จันทรคติที่ไม่มีอยู่จริง
400INVALID_RANGEtoYear มาก่อน fromYear หรือเกิน 101 ปี
400INVALID_TIMEbirthTime ไม่ใช่รูปแบบ HH:mm
400INVALID_LOCATIONส่ง birthLatitude · birthLongitude เพียงค่าเดียว
409saju_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 / personABirthLongitude
personBBirthLatitude / 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 · personAIsLeapMonth
personBCalendar · 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 ต่อครั้งเหมือนเดิม)

สำหรับผู้ที่ทราบเวลาเกิด ให้ส่งประเทศเกิดและ "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"
  }
}

ประเภทความสัมพันธ์ (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 }, ... }
  }
}

ข้อควรระวัง

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400INVALID_BIRTH_YEARปีเกิดของคนใดคนหนึ่งอยู่นอก 1900~2100
400INVALID_LUNAR_DATEวันที่จันทรคติที่ไม่มีอยู่จริง
400COMPAT_UNAVAILABLEไม่มีข้อมูลดวงสมพงษ์ของคู่เสาวันนี้
402INSUFFICIENT_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
  }
}

ราคา

รหัสข้อผิดพลาด

นอกจากข้อผิดพลาดทั่วไป (401 · 400 การตรวจเนื้อหา · 402 · 429 · 503 ฯลฯ) แล้ว นี่คือรหัสที่ API นี้ส่งออกมา:

HTTPรหัสเมื่อใด
400(ไม่มี)ดึงข้อคำถาม — tier ไม่ใช่ free · premium / ส่งคำตอบ — questionId ที่ไม่มีอยู่
400personality_axis_unansweredส่งคำตอบ — เป็น premium แต่มีแกนที่ไม่มีคำตอบเลย (แกนว่างอยู่ใน axes)
402INSUFFICIENT_BALANCEส่งคำตอบ — เป็น premium แต่ยอดคงเหลือไม่พอ

หากคำตอบอยู่นอก 1~5 จะได้ 400 ทั่วไป ทั้งหมดไม่คิดค่าบริการ

API ฐานข้อมูลการตีความ (KB)

API ที่เปิดเฉพาะบัญชีที่ยื่นขอ บัญชีที่ยังไม่เปิดจะได้ 404 kb_saju_explain_not_enabled ในทั้งสามเส้นทาง (ไม่คิดค่าบริการ) หากต้องการใช้ โปรดติดต่อฝ่ายสนับสนุน

อธิบายความสัมพันธ์ (การรวม · ปะทะ ฯลฯ) และโครงสร้าง (สิบเทพ · ก้านแฝง ฯลฯ) ที่เกิดขึ้นในผังดวงซาจูด้วยการ์ดกฎและประโยคคำอธิบาย ไม่ใช้ LLM อินพุตเดียวกันจึงได้ผลเดียวกันเสมอ

POST /api/v1/partners/v1/kb/saju/explain

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
birthobjectOฟิลด์เดียวกับเนื้อหาคำขอของ API ปฏิทินหมื่นปี (year · month · day · hour? · minute? · timezone · gender · calendar? …) birth.lang จะถูกละเว้น หากไม่รู้จัก birth.timezone การตอบกลับจะมี warnings (field: "birth.timezone") แนบมา
sectionsstring[]relations · structure · all หากละไว้คือทั้งหมด (ลำดับ relations → structure)
levelstringL1 (ค่าเริ่มต้น) · L3 รายการที่ไม่มีคำอธิบาย L3 จะเติมด้วย L1 และแนบ fallbackLevel
langstringรองรับเฉพาะ ko
channelstringstable (ค่าเริ่มต้น เฉพาะคำอธิบายที่ตรวจทานแล้ว) · 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": []
  }
}

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รหัสเมื่อใด
404kb_saju_explain_not_enabledบัญชีที่ไม่ได้ยื่นขอ (ใช้ร่วมกันทั้งสามเส้นทาง)
400INVALID_LUNAR_DATE · INVALID_LOCATIONexplain — วันที่จันทรคติที่ไม่มีอยู่จริง / ส่งละติจูด · ลองจิจูดเพียงค่าเดียว
403KB_PREVIEW_NOT_ALLOWEDexplain — บัญชีที่ไม่ได้รับอนุญาต channel: "preview" (ไม่คิดค่าบริการ)
400KB_DOMAIN_UNKNOWNrelease — domain ที่ไม่รองรับ
404KB_RULE_NOT_FOUNDrules — id กฎที่ไม่มีอยู่
503KB_NOT_LOADEDฉบับของฐานข้อมูลการตีความยังไม่ถูกโหลด ลองใหม่อีกครั้งในภายหลัง

explain คิดค่าบริการเฉพาะการเรียกที่สำเร็จ การเรียกที่ล้มเหลวจะถูกบันทึกเป็น ₩0

API ส่งอีเมลของแอป

API สำหรับให้แอปที่อัปโหลดบน RIDM Apps ส่งอีเมลแจ้งธุรกรรม · บริการ เช่น ยืนยันการสมัคร · แจ้งคำสั่งซื้อ · รีเซ็ตรหัสผ่าน เรียกได้เฉพาะด้วยคีย์สำหรับแอป (HRUM_API_KEY คอนโซล > แอปของฉัน > เชื่อมต่อ AI) หากเรียกด้วยคีย์ API ทั่วไปจะตอบ 403 MAIL_APP_KEY_REQUIRED คอนเทนเนอร์ของแอปปิดพอร์ต SMTP ไว้ จึงให้ส่งอีเมลผ่าน API นี้

POST /api/v1/partners/v1/mail/send

พารามิเตอร์คำขอ

พารามิเตอร์ชนิดจำเป็นคำอธิบาย
tostring | string[]Oที่อยู่ผู้รับ 1~10 รายการ ไม่รับที่อยู่ที่มีชื่อ (ชื่อ <ที่อยู่>)
subjectstringOหัวเรื่อง 1~200 ตัวอักษร ไม่มีการขึ้นบรรทัดใหม่
textstring△เนื้อหา (ข้อความธรรมดา) ต้องมี text หรือ html อย่างใดอย่างหนึ่ง สูงสุด 100,000 ตัวอักษร
htmlstring△เนื้อหา (HTML) สูงสุด 200,000 ตัวอักษร จะถูกจัดระเบียบก่อนส่ง: ลบ script · style · iframe · ฟอร์ม · แอตทริบิวต์อีเวนต์ ลิงก์คงไว้เฉพาะ http(s) · mailto · tel และรูปภาพเฉพาะ https หากไม่มี text จะสร้างเนื้อหาข้อความธรรมดาจาก HTML แล้วส่งไปด้วย
replyTostringที่อยู่สำหรับรับอีเมลตอบกลับ หากไม่มีจะใช้ที่อยู่ที่ตั้งไว้ในคอนโซล หากไม่มีอีกจะส่งโดยไม่มีที่อยู่ตอบกลับ
attachmentsobject[]ไฟล์แนบสูงสุด 3 ไฟล์ รวมไม่เกิน 512KB { "filename", "contentType", "content" } (content เป็น base64) รับเฉพาะ PDF · PNG · JPEG · GIF · WebP · TXT · CSV · ICS
kindstringtransactional (ค่าเริ่มต้น) · 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 รายการต่อนาทีต่อแอป

ข้อผิดพลาด

HTTPcodeคำอธิบาย
400MAIL_INVALIDคำขอไม่ถูกต้อง เหตุผลอยู่ใน reason (invalid_recipient, too_many_recipients, subject_invalid, advertising_not_allowed, body_required, attachment_type_not_allowed, attachments_too_large ฯลฯ)
402insufficient_creditเครดิตไม่พอจ่ายส่วนการส่งเพิ่มเติม จะไม่ส่งอะไรเลย
403MAIL_APP_KEY_REQUIREDเรียกด้วยคีย์ที่ไม่ใช่คีย์สำหรับแอป
403APP_NOT_ACTIVEแอปที่ผูกกับคีย์ไม่ได้อยู่ในสถานะให้บริการ
402MAIL_OVERAGE_UNPAIDค่าอีเมลส่วนเพิ่มที่ยังหักไม่ได้มากกว่ายอดคงเหลือ เมื่อเติมเงินจะหักค่าค้างแล้วเปิดใหม่ (การส่งภายในจำนวนที่รวมยังทำได้ตามเดิม)
403MAIL_EMAIL_UNVERIFIEDไม่มีบัญชีคอนโซลที่ยืนยันอีเมลแล้ว
403MAIL_SUSPENDEDการส่งอีเมลของแอปนี้ถูกระงับเพราะเกินเกณฑ์การรายงานสแปม · การตีกลับ หรือผู้ดูแลระบบระงับ
429MAIL_RATE_LIMITEDเกินเพดานต่อนาที ส่งใหม่หลัง retryAfterSeconds
429MAIL_DAILY_CAP_EXCEEDEDเกินเพดานรายวัน จะเปิดใหม่เที่ยงคืนตามเวลาเกาหลี
429MAIL_MONTHLY_LIMITใช้จำนวนที่รวมของเดือนนี้หมดแล้ว (แพ็กเกจฟรี หรือปิดการส่งเพิ่มเติม)
503MAIL_UNAVAILABLEใช้เซิร์ฟเวอร์อีเมลไม่ได้ ลองใหม่อีกครั้งในภายหลัง

แสดงจำนวนผู้ออนไลน์ตอนนี้บนเว็บเมตาเวิร์ส

ฟีเจอร์ฟรีที่แสดง "ตอนนี้มี N คนออนไลน์" บนพื้นที่ 3D บนเว็บอย่าง Three.js หรือหน้าเว็บทั่วไป เมื่อลงทะเบียนเว็บไซต์ที่คอนโซล > จำนวนผู้ออนไลน์ จะได้คีย์เว็บไซต์สาธารณะ (pk_presence_…) และสคริปต์หนึ่งบรรทัด เรียกจากเบราว์เซอร์ได้ทันทีโดยไม่ต้องใช้คีย์ · เข้าสู่ระบบ

ใส่สคริปต์

ใส่สคริปต์ที่ได้จากคอนโซล > จำนวนผู้ออนไลน์ลงในหน้าหนึ่งบรรทัด และใส่ 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 ก่อนตัวเลขมาจะว่างไว้

ใช้ตัวเลขเอง

สคริปต์จะสร้าง 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_…) ต่อเว็บไซต์ได้ที่คอนโซล > จำนวนผู้ออนไลน์ คีย์เซิร์ฟเวอร์จะแสดงเพียงครั้งเดียวตอนออก จึงให้เก็บไว้ในตัวแปรสภาพแวดล้อมของเซิร์ฟเวอร์ และอย่าใส่ในโค้ดของหน้า · เบราว์เซอร์ หากออกใหม่ คีย์เซิร์ฟเวอร์เดิมจะหยุดทันที

จำนวนคนแยกตามห้อง (ไม่บังคับ)

หากเป็นเซิร์ฟเวอร์ที่แบ่งห้อง (ช่อง · อินสแตนซ์) ใช้ ก็ส่งจำนวนคนและความจุของแต่ละห้องไปในเนื้อหา 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" } }
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"
} }

เก็บคีย์เซิร์ฟเวอร์ไว้บนเซิร์ฟเวอร์เท่านั้น หากใส่ 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 ดำเนินการ เช่น เมตาโมอา หากที่อยู่เว็บไซต์ไม่ตรงกับที่อยู่ที่อนุญาตจะไม่แสดง ปิดได้ทุกเมื่อ

ข้อมูลส่วนบุคคล

ข้อผิดพลาด

HTTPcodeคำอธิบาย
400PRESENCE_BAD_REQUEST · INVALID_BODYรูปแบบ siteKey · sid ไม่ถูกต้องหรือเนื้อหาไม่ใช่ JSON
401PRESENCE_SECRET_REQUIREDไม่มีคีย์เซิร์ฟเวอร์หรือไม่ถูกต้อง (รวมกรณีส่งด้วยคีย์สาธารณะ) — เฉพาะ count
403PRESENCE_ORIGIN_NOT_ALLOWEDไม่มี Origin หรือไม่อยู่ในที่อยู่ที่อนุญาต
404PRESENCE_SITE_NOT_FOUNDคีย์ที่ไม่มีอยู่หรือถูกยกเลิกแล้ว
413PAYLOAD_TOO_LARGEเนื้อหาเกิน 1KB
429PRESENCE_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 ด้านล่าง ซึ่งเปิดเฉพาะกับโทเค็นที่คนติ๊กไว้ตอนออก

โทเค็นจัดการคอนโซล

  1. AI ใส่งานที่จะทำ (อะไร · จำนวนเงิน · เป้าหมาย) แล้วเรียก POST /api/v1/partners/v1/console-ai/consents และได้ consentUrl กับ code
  2. AI แสดงลิงก์ให้ผู้ใช้ (MCP อาจเปิดในเบราว์เซอร์ให้ด้วย)
  3. เมื่อผู้ใช้เปิดลิงก์ขณะเข้าสู่ระบบคอนโซลอยู่ จะเห็นป้าย "AI เป็นผู้ขอ" พร้อมรายละเอียดคำขอต้นฉบับ (จำนวนเงิน · เป้าหมาย · ชื่อ) ตรวจสอบแล้วกด "ยินยอม" ส่วนการชำระเงิน คนจะทำเองอีกครั้งที่หน้าต่างชำระเงินของ Toss ต่อจากนั้น
  4. 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 · usedread (โทเค็นแรกใช้ 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?})keyskey_issue
POST /keys/{id}/rotateออกคีย์ใหม่ + ปิดคีย์นี้ทันทีkeyskey_rotate
POST /keys/{id}/revokeยกเลิกคีย์ (ย้อนกลับไม่ได้)keyskey_revoke
POST /credit/topup-linkลิงก์ชำระเงินเพื่อเติมเงิน ({planKey})creditcredit_topup_link
POST /credit/refund-previewคำนวณจำนวนเงินที่คืนได้ (ไม่ได้ยื่นขอ)creditcredit_refund_preview
POST /hosting/applyสมัครโฮสติ้ง ({planKey, subdomain, recurringConsent?})hostinghosting_apply
POST /hosting/apps/{id}/cancelยกเลิกโฮสติ้งhostinghosting_cancel
POST /seller/apply-linkลิงก์หน้าลงทะเบียนผู้ขายsellerseller_apply_link

เนื้อหาของคำขอเขียนคือค่าเดียวกับ payload ของคำขอความยินยอม + consentCode คีย์ API ใหม่จะแสดงเพียงครั้งเดียวในการตอบกลับนั้น

หมายเลขบัตรและข้อมูลส่วนตัวของผู้ขายไม่รับผ่านเส้นทาง AI การชำระเงินด้วยบัตรทำในหน้าต่างชำระเงินของ Toss ส่วนข้อมูลส่วนตัว · บัญชีธนาคาร · การยอมรับข้อตกลงของผู้ขาย คนต้องป้อนเองบนหน้าจอคอนโซล หาก payload มีค่านอกเหนือรายการที่กำหนดจะถูกปฏิเสธด้วย 400 UNKNOWN_FIELD

รหัสข้อผิดพลาด

รหัสHTTPความหมาย
MGMT_TOKEN_INVALID401ไม่มีโทเค็นหรือหมดอายุ · ถูกยกเลิก ให้ออกใหม่
MGMT_SCOPE_DENIED403โทเค็นนี้ไม่มีสิทธิ์เขียนที่จำเป็น (ฟิลด์ scope) ให้ติ๊กสิทธิ์นั้นแล้วออกใหม่
ACCOUNT_SUSPENDED403บัญชีถูกระงับ
CONSENT_REQUIRED400คำขอเขียนไม่มี consentCode
CONSENT_PENDING409คนยังไม่ได้ยินยอม
CONSENT_DENIED403คนปฏิเสธ
CONSENT_EXPIRED410หมดอายุเพราะเกิน 10 นาที
CONSENT_USED409รหัสความยินยอมที่ใช้ไปแล้ว
CONSENT_MISMATCH409รายละเอียดที่ยินยอม (จำนวนเงิน · เป้าหมาย) ต่างจากคำขอตอนนี้
CONSENT_NOT_FOUND404รหัสที่ไม่มีอยู่หรือเป็นรหัสของบัญชีอื่น
INVALID_CONSENT_PAYLOAD400ค่า payload ไม่ถูกต้อง (ฟิลด์ field)
UNKNOWN_FIELD400มีรายการที่ไม่รับผ่านเส้นทาง AI
CONSENT_RATE_LIMITED429คำขอความยินยอมมากเกินไป
MGMT_TOKEN_LIMIT409มีโทเค็นที่ใช้งานได้ 10 รายการแล้ว จึงออกเพิ่มไม่ได้
NOT_AVAILABLE404เมนูที่ยังไม่เปิด

ใช้ผ่าน 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รหัสเมื่อใด
429GUEST_QUOTA_EXCEEDEDIP เดียวกันเกิน 5 ครั้งในเดือนนี้ (รวมกับผังดวงกำเนิดสำหรับผู้เยี่ยมชม)
400INVALID_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 ของปฏิทินหมื่นปี ประเภทของค่าคือก้านฟ้า · กิ่งดิน · ธาตุทั้งห้าข้างต้น และสิบเทพ (비견 · 겁재 · 식신 · 상관 · 편재 · 정재 · 편관 · 정관 · 편인 · 정인)

โทนคำพูด (candor)

t, f (ค่าเริ่มต้น) — ไม่สนตัวพิมพ์เล็ก-ใหญ่ ค่าเดิม blunt ปรับเป็น t และ balanced · gentle ปรับเป็น f ค่าอื่นได้ 400 (โทนคำพูด (ชื่อชั่วคราว))

รหัสข้อผิดพลาด

ทุก API คืนข้อผิดพลาดทั่วไปด้านล่างด้วยวิธีเดียวกัน ตารางข้อผิดพลาดในแต่ละหัวข้อ API ระบุเฉพาะรหัสที่ออกจาก API นั้นเท่านั้น คำขอจะถูกตรวจตามลำดับต่อไปนี้ หากติดที่ขั้นก่อนหน้า ขั้นถัดไปจะไม่ทำงาน

  1. กฎความปลอดภัย — กรอง User-Agent ที่ถูกบล็อกก่อนถึงเซิร์ฟเวอร์ API (403 เนื้อหาเป็น HTML error 1010) ตอนนี้ยังไม่ได้ตรวจคีย์ API จึงเป็น 403 ไม่ใช่ 401
  2. เพดานป้องกันบริการ — เพดานต่อนาทีของคำขอทั้งหมดจาก IP เดียวกัน (429 ไม่มี code)
  3. คีย์ API — ตรวจ X-Partner-Api-Key (401)
  4. การเปิดฟีเจอร์ — ฟีเจอร์ที่ยังไม่เปิดในบัญชี (404 *_not_enabled)
  5. ข้อจำกัดคำขอ — ข้อจำกัดต่อวินาที · ต่อวันที่ตั้งในคอนโซล (429 RATE_LIMIT_EXCEEDED)
  6. การตรวจเนื้อหา — ชื่อ · ชนิด · ช่วงของฟิลด์ (400)
  7. ยอดคงเหลือ · การคำนวณ · การเรียก — ยอดคงเหลือไม่พอ (402) ข้อผิดพลาดอินพุตเฉพาะของ API ข้อผิดพลาดของโมเดลภายนอก

ข้อผิดพลาดทั่วไป

HTTP รหัส เมื่อใด การคิดค่าบริการ
400(ไม่มี)ตรวจเนื้อหาไม่ผ่าน — ส่งฟิลด์ที่ไม่มีในตาราง หรือชนิด · ช่วงไม่ถูกต้อง message เป็นอาร์เรย์สตริงไม่มี
401(ไม่มี)ไม่มี X-Partner-Api-Key คีย์ไม่ถูกต้อง คีย์ที่ยกเลิกแล้ว บัญชีที่ไม่ได้ใช้งานไม่มี
402INSUFFICIENT_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 นาทีไม่มี
429RATE_LIMIT_EXCEEDEDเกินข้อจำกัดต่อวินาที · ต่อวันที่ตั้งในคอนโซล จะมี retryAfterSeconds ในเนื้อหาและเฮดเดอร์ Retry-After แนบมาไม่มี
500(ไม่มี)ข้อผิดพลาดของเซิร์ฟเวอร์ ยอดที่หักไปแล้วในคำขอนี้จะคืนให้หลังการตอบกลับคืนเงิน
503SERVICE_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 > ข้อจำกัดคำขอ จะปกป้องยอดคงเหลือจากคีย์รั่วไหลหรือลูปไม่สิ้นสุดได้ หากเว้นว่างไว้จะใช้เพียงเพดานป้องกันบริการข้างต้น

การคิดค่าบริการ

การเรียก 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 (สร้างรูปภาพ · ขายต่อโมเดล) ราคาคงที่ต่อรูปตามโมเดล · ความละเอียด · คุณภาพ — ตารางราคา

ทดสอบแบบผู้เยี่ยมชม

Idempotency

ทุกคำขอที่สำเร็จจะคิดค่าบริการแยกกัน หากส่งคำขอเดิมซ้ำ จะคำนวณ · สร้างใหม่และคิดค่าบริการอีกครั้ง การลองใหม่ซ้ำซ้อนหรือการนำอินพุตเดิมกลับมาใช้ จึงให้ไคลเอนต์เก็บการตอบกลับไว้แล้วจัดการเอง (เช่น แคชที่ใช้แฮชของคำขอเป็นคีย์)

เฮดเดอร์ X-Idempotency-Key (สูงสุด 128 ตัวอักษร — หากยาวกว่านั้นจะบันทึกเพียง 128 ตัวแรก) ยังรับได้ แต่ไม่ได้ป้องกันการคิดค่าบริการ คีย์ที่ส่งจะถูกบันทึกใน idempotencyKey ของบันทึกการใช้งานตามเดิม ใช้เทียบได้ว่าคำขอใดถูกประมวลผลด้วยการเรียกใด กับ ID คำสั่งซื้อ · งานฝั่งพาร์ทเนอร์

ข้อยกเว้น: การอ่านโหงวเฮ้ง · ลายมือ หากส่งคีย์เดียวกัน · เนื้อหาเดียวกันซ้ำภายใน 24 ชั่วโมง จะคืนผลครั้งแรกและไม่คิดค่าบริการใหม่ (การลองใหม่และการส่งซ้ำ)

ข้อยกเว้น: ศาสตร์ชื่อ หากส่งคีย์เดียวกัน · เนื้อหาเดียวกันซ้ำภายใน 24 ชั่วโมง จะคืนผลครั้งแรกและไม่คิดค่าบริการใหม่ (การลองใหม่และการส่งซ้ำ)

ฝ่ายสนับสนุน

หากติดขัดระหว่างการเชื่อมต่อ หรือการตอบกลับไม่ตรงกับเอกสาร โปรดแจ้งให้เราทราบ

เรื่องที่ติดต่อช่องทางติดต่อ
สนับสนุนด้านเทคนิค · แจ้งเหตุขัดข้อง · ความร่วมมือ contact@float.do

เมื่อติดต่อ หากส่งข้อมูลด้านล่างมาด้วยจะตรวจสอบได้เร็วขึ้น

เรื่องเกี่ยวกับข้อกำหนดและการจัดการข้อมูลส่วนบุคคล โปรดดูข้อกำหนดการใช้งาน (ภาษาเกาหลี)และนโยบายความเป็นส่วนตัว (ภาษาเกาหลี)