APIガイド
このAPIスタックが実際のサービスでどう動くか気になりますか? 同じエンジンで動くAI四柱推命(サジュ)アプリ INTA – Life is Timing で、四柱推命分析とAIチャットを試せます。 INTAはこのAPIの実稼働リファレンスです。 INTAのAI音声応答(TTS)も同じスタックで動いています — 音声APIは今後提供予定です。
AIにアプリを作らせよう — 無料電子書籍(韓国語)
本を選ぶ(韓国語)オールインワン占いアプリ(韓国語)キャラクターチャットアプリ(韓国語)会員制Webアプリ(韓国語)Apps in Toss ミニアプリ(韓国語)
クイックスタート
HRUMは、記憶するAI・四柱推命分析・LLM再販を提供しています。次の3ステップで始められます。
ベースURLは https://api.hrum.ai(API)と https://console.hrum.ai(コンソール)です。旧アドレスの api.float.do、console.float.do、api.inta.do も引き続き使えるため、すでに連携済みの場合は変更不要です。
- APIキーを取得する - コンソールに新規登録し、APIキー画面でキーを作成します(キーは作成直後に一度だけ表示されます)。新規登録からエラー処理までの全手順は開発者向け「はじめに」ガイドにあります。
- リクエストを送る - 下の例に沿ってPOSTリクエストを送ります。
- レスポンスを処理する - JSONレスポンスから四柱推命データを取り出します。
curl -X POST https://api.hrum.ai/api/v1/partners/v1/manseryeok \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"year": 1990,
"month": 1,
"day": 15,
"hour": 14,
"minute": 30,
"timezone": "Asia/Seoul",
"gender": "male"
}'
User-Agentに注意: Python標準の urllib のデフォルトUser-Agent(Python-urllib/3.x)はセキュリティルールに引っかかり、403(error 1010)になります。requests、OpenAI SDK、Node、curlは問題ありません。urllib や独自のHTTPクライアントを使う場合は、User-Agent: <app-name>/<version> ヘッダーを自分で設定してください。
(実測:python-requests 通過・OpenAI/Python 通過・node 通過・Python-urllib 403)
節約のコツ — 結果を保存して再利用しましょう。 成功したリクエストはすべて個別に課金されます。万歳暦(マンセリョク)・紫微斗数・相性・西洋占星術・生涯四柱の結果は、同じ生年月日時・同じオプションなら毎回同一です。最初のレスポンスをDBに保存し(たとえばリクエスト本文のハッシュをキーにして)、以降は保存した値を使ってください。今日の運勢や運勢フローのように日付で変わる結果は、キーに日付を含めます。詳しくは冪等性をご覧ください。
APIリファレンス
HRUMは、記憶するAI・四柱推命分析・LLM再販を提供しています。
- 変更(2026-10-14): 韓国語のレスポンス文が一貫した丁寧体に統一されました。内容やフィールドの変更はありません
- 追加(2026-10-14): タイムゾーン名が認識できない場合、成功レスポンスに
warnings(UNKNOWN_TIMEZONE)が付きます。計算は従来どおりデフォルトのタイムゾーンで行われ、警告がなければレスポンスは従来と同じです — レスポンスの警告 - 追加(2026-10-17): AI四柱推命リーディング・リーディングメモリー・レポートの
birthで、万歳暦APIと同じ出生地・タイムゾーン・閏月フィールド(isLeapMonth、timezone、座標、country、zaSiRule、birthTimePrecision)を受け付けるようになりました。送らなければ計算は従来と同じです — AI四柱推命リーディングAPI
RIDM Memory API
エンドユーザーごとの会話メモリーをホスティングし、ridm/* モデルにメモリー層を加えます。メモリーは ridm/* 専用です。OpenAI/Googleモデルはそのまま再販します — 同じモデルで、製品が違います。YouTube字幕の自動挿入にも対応しています。
セッションなし — 終わりのない1つのセッションです。 同じ user で呼び出せば、会話はそのまま続きます。呼び出しのたびにサーバーが直近 historyCount 件の会話ターンと recallCount 件の長期記憶(要約・プロフィール・記憶した事実・継続中の悩み)を自動で付けるので、送るのは新しいメッセージ1件だけです。どこまで遡るかは2つの数値で調整し、memoryCap でエンドユーザーごとの最大保存メッセージ数を設定します。履歴を自分で管理したい場合は、historyCount を省略し、以前の会話をOpenAI方式で messages に入れて送ってください。
会話が長くなってもコストは比例して増えません。 古いアシスタントターンは自動で圧縮されます — 直近2ターンは原文のまま残り、それより前のターンは500文字から200文字へ段階的に短くなり、入力トークンを節約します(ユーザーターンはそのまま)。また、ユーザーが以前の発言について尋ねると(「前に〜って言ってたよね」)、サーバーが保存済みの会話を検索し、日付と話者付きで引用します(recalledMemories に含まれます)。記録がなければ、作り話をせずにそう伝えます。
LLM API(再販)と 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 になります) |
✓(要約サイクルを含む) |
| モデレーション | ユーザーメッセージのみ | システム+ユーザーメッセージ |
systemPrompt の上限 |
無視 — 再販モデルはsystemPromptを無視するため、messages に {"role":"system"} として入れてください |
8,000文字で検証(ridmのみ) |
| 追加のレスポンスフィールド | costUsd、costWon(費用) |
costWon、recalledMemories、memorySaved、memoryCapReached、filesRecalled、emotion、customProfile |
| 料金 | 原価 × 為替レート × 1.10 | 再販価格 × 1.30(メモリー・想起・感情・ファイル自動想起をすべて含む。機能ごとの課金なし) |
| 例外 | — | ridm/saju-report:メモリーなし → 再販マージンのみ、チャットなし(レポート専用) |
コード例の比較
// 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を無視するため、messages に {"role":"system"} として入れてください。 |
|
youtube |
boolean | trueにすると、最後のメッセージ内のYouTubeリンクの字幕を挿入します | |
stream |
boolean | レスポンスをストリーミングするかどうか(デフォルト:false)。下記のストリーミング(SSE)形式を参照してください — 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 の場合、messagesまたはsystemPromptに「JSON」という単語が必要)。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 には新しいメッセージだけを送れば済みます。省略するとサーバー側の履歴は付かず、messages の最後の10件だけが使われます。 |
|
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つの四柱推命リーディングAPI(リーディング、リーディングメモリー、レポート)で同じように動作します。
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 の場合、レスポンスはOpenAIのチャンクではなく、名前付きのSSEイベントで届きます。そのためOpenAI SDKのストリームパーサーでは読めません — SSEは自分でパースしてください(非ストリーミングのレスポンスはOpenAI互換です)。
| イベント | data |
|---|---|
event: chunk |
RIDM:{"delta":"…"}(ツール呼び出し時は tool_calls の断片を含む) / 再販:アップストリームのチャンクオブジェクトそのまま |
event: message_done |
RIDM:{finish_reason, usage, costWon, recalledMemories, memorySaved, memoryCapReached, emotion?, customProfile?, budgetExceeded?, tool_calls?} / 再販:{finish_reason, usage, costUsd, costWon, budgetExceeded?}。id、choices、model はありません |
event: error |
{message, code, status} — ヘッダー(200)は送信済みなので、実際のエラーステータスは status で確認してください |
data: [DONE] |
正常終了マーカー(最終行) |
event: chunk
data: {"delta":"안녕하세요"}
event: message_done
data: {"finish_reason":"stop","usage":{"prompt_tokens":1250,"completion_tokens":320,"prompt_tokens_details":{"cached_tokens":0}},"costWon":45,"recalledMemories":[],"memorySaved":{"id":"turn-1756200000000","keywords":[]}}
data: [DONE]
エラーコード
共通エラーに加えて、このAPIが返すコードです。stream: true の場合、レスポンス開始後のエラーは event: error({message, code, status})で届きます。再販モデルも同じ表に従います。
| コード | HTTP | 説明 |
|---|---|---|
MODERATION_FLAGGED | 400 | モデレーションでブロック(ridm:system+user、再販:userメッセージ) |
INSUFFICIENT_BALANCE | 402 | 残高不足(要求した出力全体を先に確保して確認) |
MODEL_NOT_FOUND | 400 | モデルが設定されていません |
INVALID_TOOLS / TOOLS_UNSUPPORTED_FOR_MODEL | 400 | toolsフィールドの不整合 / Claudeモデルでツール呼び出しを要求 |
FILE_NOT_FOUND | 400 | fileIds に存在しない(または他のパートナーの)ファイルが含まれています |
FEATURE_DISABLED | 403 | その機能をオフにしたアカウントでyoutube・files・emotionオプションを使用 |
RATE_LIMITED | HTTP 400、本文の status 429 | アップストリームのレート制限、または1日の再販利用上限を超過(デフォルト:パートナーごとに₩100,000/日) |
UPSTREAM_TIMEOUT | HTTP 400、本文の status 504 | アップストリームの応答がタイムアウト(60秒) |
UPSTREAM_INVALID_REQUEST | 400 | アップストリームのモデルがリクエストを拒否(upstream 400/422) |
INVALID_RESPONSE_FORMAT | 400 | response_format: json_object なのにメッセージに「json」という単語がない(OpenAI系) |
REPORT_ONLY_MODEL | 400 | ridm/saju-report が指定されました — 四柱推命レポートAPI専用です |
| (なし) | 400 | ridm/* モデルで user がない・systemPrompt が8,000文字超・未対応のモデルプレフィックス |
provider_not_configured | 503 | 現在Claudeモデルに接続されていません |
補足
- YouTube字幕の挿入: youtube:trueの場合、最後のメッセージ内のYouTubeリンクから字幕を抽出し、入力トークンに含めます。字幕を取得できない場合は挿入せずに会話が続き、
youtubeUsedは空配列で返ります(単体のYouTube要約APIのみ、課金なしで400を返します)。 - 元のモデルとの互換性: model値がopenai/*・google/*・anthropic/*の場合、メモリー機能なしで元のモデルをそのまま呼び出します(原価 × 為替レート × 1.10)。
- プロンプトキャッシュ割引: OpenAI系モデル(openai/*、ridm/gpt-*)で同じプレフィックス(1,024トークン以上)を繰り返し送ると、アップストリームのキャッシュにヒットした入力トークンは入力単価の30%で課金されます。レスポンスの
usage.prompt_tokens_details.cached_tokensとGET /usage/logsのcachedTokensで確認できます。キャッシュがヒットするかは、アップストリームのポリシーにより呼び出しごとに異なる場合があります。Googleモデルにはキャッシュがないため、入力単価が全額適用されます。 Claudeモデルもキャッシュを要求しないため、入力単価が全額適用されます。 - REPORT_ONLY_MODELは対象外: ridm/saju-reportはメモリーなしの単発専用なので、このエンドポイントでは使えません(400)。
カスタムプロフィール
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フィールド、値1件あたりデフォルト150文字(最大500)。 |
profileValueMaxChars |
number | 値1件あたりの最大文字数(デフォルト150、最大500 — それより大きい値は500に切り詰め)。そのリクエストで保存される値(endUserProfile と今回の要約サイクルで抽出された値)にのみ適用されます。保存されないため、毎回のリクエストで送ってください。 |
リクエスト例(RIDMチャット)
{
"model": "ridm/gpt-5.6-terra",
"user": "enduser_123",
"messages": [
{ "role": "user", "content": "Help me plan my kid's birthday party tomorrow" }
],
"extractProfileFields": ["childAge", "interests", "budget", "constraints"],
"injectProfileFields": ["name", "childAge", "interests"],
"endUserProfile": {
"name": "Jane Kim",
"childAge": "7",
"interests": "science, art"
},
"profileValueMaxChars": 200
}
レスポンス内のプロフィール
プロフィールパラメータを送ったリクエストのレスポンス(ストリーミング時は message_done)には、customProfile フィールドが付きます。
"customProfile": {
"injected": ["name", "childAge", "interests"], // fields injected into this turn's prompt
"stored": 4, // number of fields currently stored
"extractPending": ["budget"] // extraction targets that have no value yet
}
削除API
特定のフィールドを削除するには、DELETEリクエストを送ります。
DELETE /api/v1/partners/v1/profile/{endUserId}/field/{key}
X-Partner-Api-Key: your-api-key
レスポンス:{ "success": true, "data": { "deleted": true } } — キーが存在しない場合や未知の endUserId でも、200と "deleted": false が返ります(新しいエンドユーザーは作成されません)。このAPI固有のエラーコードはなく、共通エラーのみです。
制限と制約
- フィールド上限: エンドユーザーごとに最大100フィールド。それを超えると古いフィールドから削除されます。
- 値の長さ: フィールドごとにデフォルト150文字、最大500文字。profileValueMaxCharsで調整できます。
- 蓄積型の保存: extractProfileFieldsで抽出した値は蓄積され、空またはnullの値はスキップされて既存の値が保たれます。フィールドが削除されるのは上記の削除APIを使ったとき(または100件を超えて古い順に自動削除されたとき)だけです。endUserProfileで設定した値は抽出値を上書きします。
- 値の長さはリクエストごと: profileValueMaxCharsは保存されず、そのリクエストで保存される値にのみ適用されます。
- Soft Update: スキーマ(フィールド名)が変わっても既存の値は保たれ、呼び出しのたびに新しい値とマージされます。
- ridm/* のみ: 再販モデル(openai/*、google/*)はプロフィールを無視します。
LLM API(再販)
openai/*、google/* などの元のLLMモデルの再販です(メモリーなし、元のレスポンスそのまま)。再販モデルへのリクエストでは、user、systemPrompt、recallCount、memoryCap、summaryEvery、emotion、candor は無視され(システム指示は messages に {"role":"system"} として入れてください)、レスポンスにメモリーフィールド(recalledMemories など)は付きません。料金 = 原価 × 為替レート × 1.10。
利用可能なモデル(GET /api/v1/partners/v1/models と同じリスト)
- OpenAI(23):
openai/gpt-6-astra·openai/gpt-6-sol·openai/gpt-6-luna·openai/gpt-5.6-sol·openai/gpt-5.6-terra·openai/gpt-5.6-luna·openai/gpt-5.5·openai/gpt-5.4·openai/gpt-5.4-mini·openai/gpt-5.4-nano·openai/gpt-5.2·openai/gpt-5.1·openai/gpt-5·openai/gpt-5-mini·openai/gpt-5-nano·openai/gpt-4.1·openai/gpt-4.1-mini·openai/gpt-4.1-nano·openai/gpt-4o·openai/gpt-4o-mini·openai/o3·openai/o3-mini·openai/o4-mini - Google(3):
google/gemini-3.5-flash·google/gemini-3.5-flash-lite·google/gemini-3.1-pro - Anthropic(13): 下記のClaudeモデルのセクションを参照
- RIDM: 上記の各モデルに対し、同じ名前に
ridm/プレフィックスを付けたメモリーモデルがあります(再販価格 × 1.3)。さらに四柱推命レポート専用のridm/saju-reportがあります(/reading/report経由でのみ呼び出し)。
curl https://api.hrum.ai/api/v1/partners/v1/models \
-H "X-Partner-Api-Key: your-api-key"
GET /api/v1/partners/v1/models のレスポンス — OpenAIの models.list 形式ではありません。価格は100万トークンあたりのウォン(₩)で、下の数値は例です。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 Memory APIでは同じ名前にridm/プレフィックスを付けます(再販価格 × 1.3)。 - 同じリクエスト形式: OpenAI形式で送れば、サーバーがClaude形式に変換します。複数のsystemメッセージは1つにまとめられます。
- temperatureとtop_pは無視: Claude 5.xはサンプリング値を受け付けないため、送っても効果はありません(エラーにはなりません)。トーンはシステムプロンプトで調整してください。
- max_tokens: 省略時は8,192です。Claude Fable 5・5.1とOpus 5・5.5は内部推論が常にオンなので、推論トークンは出力トークンとして課金されます。また、回答が途切れないよう、呼び出し時にmax_tokensへ1,500トークンの余裕が加えられます。
- Haiku 5.5のロングコンテキスト料金: 1回のリクエストの入力が100,000トークンを超えると、Anthropicの公式価格が×5の料金帯に移るため、そのリクエストの入力・出力トークンは×5で課金されます。
- 対応範囲: テキストの会話(ストリーミングを含む)。Claudeモデルはツール呼び出し(
tools、tool_choice、parallel_tool_calls)に対応しておらず、400TOOLS_UNSUPPORTED_FOR_MODELを返します — OpenAIとGoogleの再販モデルはツール呼び出しに対応しています。画像入力には対応していません。
思考(推論)モデルとmax_tokens: 非表示の思考・推論を使うモデルでは、思考トークンも出力上限に含まれます。サーバーは呼び出しに余裕を加えますが、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)と、思考が常にオンのモデル(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のリクエストで828トークン課金 — 思考747+本文81)。費用の上限を厳密に守りたい場合は、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を無視するため、messages に {"role":"system"} として入れてください |
|
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 は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のエラー表と同じです。再販モデルにも1日の利用上限(RATE_LIMITED)が適用されます。
AI四柱推命リーディングAPI
生成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):万歳暦APIと同じ任意フィールド — isLeapMonth、timezone、birthLatitude、birthLongitude、country、zaSiRule、birthTimePrecision — を同じ名前・同じルールで受け付けるため、同じ出生データなら万歳暦と同じ四柱になります。座標は2つとも送ってください。片方だけだと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 | フラットなフィールド(旧方式)。4つすべてそろっている場合のみbirth(新暦)として受け付けます。birth・saju・フラットなフィールドのどれもないと、400 MISSING_SUBJECT_INPUT になります |
|
hour / minute |
number | 出生時 0–23 / 分 0–59(任意)。hourを省略すると時柱が除かれ、年・月・日の三柱でリーディングします | |
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。カードの言語は質問の言語に従います。引いたカード(画像URLを含む)はレスポンスの tarot で返ります |
|
only |
string | 四柱推命AIの中のAIを1つだけ単独で呼び出します。saju · ziwei · astro · tarot · dream。exclude と一緒に送ると400を返します。AIを1つだけ使うを参照 |
リクエストパラメータ — toolsのオプション
| オプション | 型 | 説明 |
|---|---|---|
astrology |
boolean | trueにすると、西洋占星術のネイタルチャートをリーディングに反映します。別料金はかかりません |
youtube |
boolean | trueにすると、question 内のYouTubeリンクの字幕を挿入します(字幕の文字数 × 0.25を入力として課金)。トップレベルの youtube フィールドはありません — 必ず tools の中に入れてください |
fileIds |
string[] | 挿入するドキュメントのID(UUID、最大5件) |
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/reading \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"question": "Is this a good year to change jobs?",
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female" },
"maxLength": 600,
"tone": "warm"
}'
レスポンス例
{
"success": true,
"data": {
"interpretation": "당신의 사주에서 보이는 특징은...",
"sajuSource": "computed",
"usage": {
"inputTokens": 450,
"outputTokens": 280
},
"costPoints": 18
}
}
レスポンスフィールド
| フィールド | 説明 |
|---|---|
interpretation | 解釈テキスト |
sajuSource | computed(birthから計算) | provided(sajuの入力を使用) |
sajuMismatch | birthとsajuを両方送り、柱が食い違う場合の警告({pillars, computed, note})。それ以外はnullまたは省略 |
toolsUsed | 実際に動作したツール(例:["youtube"]) |
toolsSkipped | 要求されたがスキップされたツール [{tool, reason}]、reason:unavailable | cap_exceeded | error | auto_rejected |
filesUsed | 挿入されたドキュメントID(tools.fileIds 使用時) |
usage | 参考用のトークン数(inputTokens は四柱推命・システムプロンプトを含む実際の値で、課金の基準ではありません) |
costPoints | 実際に請求された金額(₩) |
modulesUsed | 実際に含まれたモジュール(例:["saju","ziwei","astro"]、sajuが先頭)。含まれるモジュール機能がオンのときのみ |
moduleFees | 含まれたモジュールごとの固定料金(₩)(例:{"ziwei":50,"astro":20})。costPoints に含まれ済み。含まれるモジュール機能がオンのときのみ |
tarot | タロットが含まれた場合に引いたカード — タロットAPIのレスポンスと同じ形(cards[] に imageUrl あり、question と costPoints なし) |
only | リクエストの only の値をそのまま返します(送った場合のみ)。only が saju 以外なら四柱推命は使われないため、sajuSource はありません |
support | 危機時の支援情報 {message, contacts:[{name, number, hours}]}。dream のテキストに危機を示す言葉が含まれる場合はAIを呼び出さず、interpretation に支援情報を入れて costPoints: 0 で返します。安全チェックを完了できなかった場合にも付きます |
エラーコード
共通エラーに加えて、このAPIが返すコードです。
| HTTP | コード |
|---|---|
| 400 | MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE · UNKNOWN_TOOL · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUND · INVALID_TOOL_MODE · MEMORY_REQUIRES_MEMORY_ENDPOINT · EMOTION_REQUIRES_MEMORY · MISSING_ENDUSER_ID(メモリー) · ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALID(AIを1つだけ使う) |
| 402 | INSUFFICIENT_BALANCE — 呼び出し前に maxLength × 2 トークン分(valueプランまたは韓国語以外の質問では+4,000)の出力費用を先に確保するため、最終的な請求額がそれより小さくなる場合でも拒否されることがあります |
| 403 | FEATURE_DISABLED — アカウントでオフになっている機能(youtube、files、emotion)を使用 |
含まれるモジュール — 紫微斗数・西洋占星術・夢占い・タロット
四柱推命AIには、四柱推命・紫微斗数・西洋占星術・タロット・夢占いのAIが入っています。その日の日柱(今日の気)は、別途呼び出さなくてもすべてのリーディングにデフォルトで反映されます(追加料金なし)。1回の統合呼び出しで、含まれるモジュールの計算結果を根拠としてすべてをまとめて読み解きます。不要なものは exclude で外してください。必要なAIだけを呼び出すには only を使います。計算結果だけが必要なら、同じモジュールを計算用エンドポイント(/ziwei-chart · /astrology(西洋占星術総合) · /dream · /tarot)で1つずつ呼び出し、自分のアプリを作ることもできます。/reading/memory も同じフィールドを受け付けます。
| モジュール | 含まれる条件 | 根拠として入るもの | 料金(=単体エンドポイント1回分) |
|---|---|---|---|
紫微斗数 ziwei | 生年月日+出生時刻(hour)があればデフォルトで | 命盤の要約 — 命宮・身宮・三方四正・生年四化・現在の大限と流年 | /ziwei-chart |
西洋占星術 astro | 生年月日があればデフォルトで(時刻は不要) | ネイタルチャートの要約 — 太陽・月・水星〜土星のサインと度数、アセンダント(可能な場合) | ₩20(西洋占星術の単体製品は /astrology) |
夢占い dream | dream に夢を送ったとき | 夢のテキスト+夢の中で見つかったシンボル語 | /dream(候補がなければ ₩0) |
タロット tarot | tarot を送ったとき | このリクエストで引いたカードと正位置・逆位置の意味(画像URL付きで tarot に返ります) | /tarot |
- 課金: 通常のトークン料金(質問+persona+含まれるモジュールの根拠ブロックの文字数 × 0.25を入力トークンとし、それに出力トークンを加えたもの)に加えて、含まれるモジュールごとに単体エンドポイント1回分の料金が加算されます。根拠ブロックはそれぞれ1,500文字未満の要約です。アカウントで機能がオフのモジュールや料金のないモジュールは含まれません。モジュールごとの料金と1回あたりの目安は料金ページにあります。
- 四柱(
saju)だけを送るリクエストには生年月日がないため、紫微斗数と西洋占星術は含まれません(夢占いとタロットは含まれます)。 tools.astrologyとの関係: 西洋占星術モジュールが含まれる場合、同じネイタルチャートが二重に入らないよう、tools.astrologyによるチャートの挿入はスキップされます。西洋占星術モジュールを外した場合(excludeまたは機能オフ)は、tools.astrologyが従来どおり動作します。- 夢占いの安全措置:
dreamのテキストに危機を示す言葉が含まれる場合はAIを呼び出さず、支援情報(support)をcostPoints: 0で返します。 - 機能スイッチ: 現在オンです。サーバー設定がオフになると、
exclude、dream、tarotは送っても無視され、リーディング・料金・レスポンスは含まれるモジュールが導入される前と同じになります(modulesUsed、moduleFees、tarotなし)。
リクエスト例(POST /api/v1/partners/v1/reading) — 夢占いの辞書は韓国語のみのため、夢のテキストは韓国語のままです
{
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
"question": "I can't stop thinking about last night's dream. What could it mean for me right now?",
"dream": "큰 뱀이 집 안으로 들어와 내 발 옆에 똬리를 틀었어요",
"tarot": { "spread": "past-present-future" }
}
レスポンス例
{
"success": true,
"data": {
"interpretation": "뱀이 집 안으로 들어와 곁에 머무는 꿈은...",
"sajuSource": "computed",
"modulesUsed": ["saju", "dream", "ziwei", "astro", "tarot"],
"moduleFees": { "dream": 30, "ziwei": 50, "astro": 20, "tarot": 20 },
"tarot": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": null,
"cards": [
{ "position": 1, "positionLabel": "과거", "id": "wands_10", "name": "완드의 10", "nameEn": "Ten of Wands", "arcana": "wands", "reversed": true, "keywords": ["내려놓기", "위임", "해방"], "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.", "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp" }
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp"
},
"usage": {
"inputTokens": 3140,
"outputTokens": 760
},
"costPoints": 162
}
}
四柱推命のみ(他のモジュールをすべて外す)(POST /api/v1/partners/v1/reading)
{
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
"question": "Is this a good year to change jobs?",
"exclude": ["ziwei", "astro"]
}
AIを1つだけ使う — only
四柱推命AIには、四柱推命・紫微斗数・西洋占星術・タロット・夢占いのAIが入っています。上のような1回の統合呼び出しの代わりに、only で必要なAIだけを呼び出せます。そのAIは自分の根拠(命式・ネイタルチャート・引いたカード・夢の候補)だけで答え、それ以外は加わりません。
only | 呼び出すもの | 必要な入力 | 料金 |
|---|---|---|---|
saju | 四柱推命AI(四柱推命のみ、他のモジュールなし) | birth または saju | トークン料金のみ(固定料金なし) |
ziwei | 紫微斗数AI | birth+出生時刻(hour) | トークン料金+/ziwei-chart 1回分 |
astro | 西洋占星術AI | birth(時刻は不要) | トークン料金+₩20(西洋占星術モジュールの固定料金) |
tarot | タロットAI | tarot のオプション — birth は不要 | トークン料金+/tarot 1回分 |
dream | 夢占いAI | dream に夢のテキスト — birth は不要 | トークン料金+/dream 1回分 |
- 課金: トークン料金(質問+persona+そのAIの根拠ブロックの文字数 × 0.25を入力トークンとし、それに出力トークンを加えたもの)+そのモジュールの固定料金1件分。分野ごとの1回あたりの目安料金は料金ページにあります。
excludeとは併用できません: 両方送ると400ONLY_WITH_EXCLUDEを返します。そのAIに必要な入力がない場合は400ONLY_REQUIRES_INPUT、アカウントでその機能がオフの場合は400ONLY_DOMAIN_UNAVAILABLEになります — 四柱推命リーディングに切り替わることはありません。その日付で命盤を計算できない場合は400ONLY_INPUT_INVALIDです。tarotとdreamには生年月日が不要です。birthやsajuなしで、質問とカード(または夢のテキスト)だけを送ってください。saju以外のonlyは四柱推命を使わないため、レスポンスにsajuSourceはありません。- 機能スイッチ: 含まれるモジュールと同じサーバー設定に従い、現在オンです。設定がオフになると
onlyは無視され、通常の四柱推命リーディングとして動作します。
リクエスト例 — タロットAIのみ(POST /api/v1/partners/v1/reading)
{
"question": "Should I keep pushing ahead with the job change I'm preparing?",
"only": "tarot",
"tarot": { "spread": "past-present-future" }
}
レスポンス例
{
"success": true,
"data": {
"interpretation": "과거 자리의 완드의 10 역방향은 오래 짊어진 짐을...",
"only": "tarot",
"modulesUsed": ["tarot"],
"moduleFees": { "tarot": 20 },
"tarot": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": null,
"cards": [
{ "position": 1, "positionLabel": "과거", "id": "wands_10", "name": "완드의 10", "nameEn": "Ten of Wands", "arcana": "wands", "reversed": true, "keywords": ["내려놓기", "위임", "해방"], "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.", "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp" }
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp"
},
"usage": {
"inputTokens": 1180,
"outputTokens": 720
},
"costPoints": 37
}
}
補足
- 返すのは解釈だけ: レスポンスには生成された解釈テキストだけが含まれ、内部のプロンプトや四柱推命の理論は公開されません。
candorApplied:candorをtで送った場合のみ、レスポンスに実際に適用された率直さ(t|f)が付きます。/reading/memoryも同じです(率直さ(仮称))。- 課金の基準: 入力 =(質問+personaの文字数)× 0.25トークン(+
/readingで挿入されたYouTube字幕の文字数 × 0.25)、出力 = 実際の生成トークン数。四柱推命データの挿入とシステムプロンプトは課金されず、usage.inputTokensは参考値です。含まれるモジュール(今日の運勢・紫微斗数・西洋占星術・夢占い・タロット)がオンの場合は、その根拠ブロックとモジュールごとの固定料金が加算されます。costPointsが実際に請求された金額です。 - 応答の言語: 韓国語以外の質問には、質問と同じ言語で答えます。
- 出生時刻が不明な場合: hourを省略すると時柱が除かれ、年・月・日の三柱でリーディングします。
AI四柱推命リーディング・メモリーAPI
エンドユーザーごとの会話メモリーをホスティングし、ユーザーが戻ってきたときに過去の文脈を踏まえてリーディングを続けます。継続的でパーソナライズされた相談を提供できます。料金はAI四柱推命リーディングのトークン単価の1.3×です(1Mトークンあたり:入力 KRW 3,754・出力 KRW 30,030 — リーディングは入力 KRW 2,888・出力 KRW 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):万歳暦(マンセリョク)APIと同じ任意フィールド — isLeapMonth、timezone、birthLatitude、birthLongitude、country、zaSiRule、birthTimePrecision — を同じ名前・同じルールで受け付けるため、同じ出生データからは万歳暦と同じ四柱が得られます。座標は両方送ってください。片方だけ送ると 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 | フラットなフィールド(旧形式)。4つすべてがそろっている場合のみ birth(新暦)として受け付けます。birth・saju・フラットなフィールドのいずれもない場合は 400 MISSING_SUBJECT_INPUT になります |
|
hour / minute |
number | 出生時 0–23 / 分 0–59(任意)。hour を省略すると時柱を除き、年・月・日の三柱でリーディングします | |
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 の場合、西洋占星術のネイタルチャートをリーディングに反映します。追加料金はかかりません |
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)はAI四柱推命リーディングAPIと同じです。自動で呼び出されたドキュメントは filesRecalled に入り、tools.emotion: true の場合は emotion も返ります。課金の基準(YouTubeを除く)もリーディングAPIと同じです。
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/reading/memory \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"endUserId": "member-1024",
"question": "About the job change we talked about last time: is next month a good time to make the move?",
"birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30, "gender": "female" }
}'
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | MISSING_ENDUSER_ID | endUserId が空、または空白のみ |
| 400 | MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE | 出生データまたは四柱推命の入力エラー(リーディングAPIと同じ) |
| 400 | UNKNOWN_TOOL · INVALID_TOOL_MODE · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUND | tools または fileIds のエラー。このパスは tools.emotion と tools.summaryEvery も受け付けます |
| 400 | ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALID | AIを1つだけ に関するエラー |
| 402 | INSUFFICIENT_BALANCE | 出力コストを事前に確保できなかった(リーディングAPIと同じ方式) |
| 403 | FEATURE_DISABLED | アカウントでオフになっている機能(youtube、files、emotion)を使用した |
メモリー管理API
メモリー付きAI四柱推命リーディング(POST /reading/memory)とRIDMチャット(ridm/* モデルでの user)は、同じエンドユーザーメモリーストアを共有します。以下のパスの {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 | タグでメモリーを検索(タグはカンマ区切り。RIDMメモリー料金に含まれ、追加料金なし) → {endUserId, query:{tags}, 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 を送ると、GET /memory/{endUserId} の summary に表示されます。未知の endUserId は新規作成されます。AI呼び出しがないため追加料金はかかりません → {endUserId, saved, summarySaved}(サーバーキーのみ) |
| /api/v1/partners/v1/memory/{endUserId} | DELETE | そのエンドユーザー向けにアップロードされたファイル(/files)を含め、エンドユーザーのメモリーをすべて削除 → 204(本文なし) |
リクエストとレスポンスの例
# Get stored memory
curl https://api.hrum.ai/api/v1/partners/v1/memory/member-1024 \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"summary": "이직을 고민 중이며 다음 달 면접을 앞두고 있다...",
"metaSummary": "...",
"tags": ["이직", "면접"],
"profile": null,
"concerns": ["..."],
"facts": []
}
}
# Message list (oldest first)
curl "https://api.hrum.ai/api/v1/partners/v1/memory/member-1024/messages?limit=2&offset=0" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"messages": [
{ "id": "...", "role": "user", "content": "이직 고민이 있어요", "tags": ["이직"], "createdAt": "2026-10-11T09:00:00.000Z" },
{ "id": "...", "role": "assistant", "content": "...", "tags": [], "createdAt": "2026-10-11T09:00:04.000Z" }
],
"offset": 0,
"limit": 2,
"total": 18
}
}
# Tag search (tags as stored: 이직 = job change, 면접 = interview)
curl "https://api.hrum.ai/api/v1/partners/v1/memory/search?endUserId=member-1024&tags=이직,면접" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"endUserId": "member-1024",
"query": { "tags": ["이직", "면접"] },
"results": [
{ "id": "...", "summary": "다음 달 면접 일정을 이야기함", "level": 0, "tags": ["면접"], "createdAt": "2026-10-11T09:00:00.000Z" }
]
}
}
# Save a conversation (no AI generation)
curl -X POST https://api.hrum.ai/api/v1/partners/v1/memory/member-1024/turns \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "user", "content": "I'\''m worried about my interview next month" },
{ "role": "assistant", "content": "You'\''ve prepared well. You'\''ll do fine." }
],
"summary": "Call about feeling anxious before next month'\''s interview",
"tags": ["interview"]
}'
{
"success": true,
"data": {
"endUserId": "member-1024",
"saved": 2,
"summarySaved": true
}
}
# Delete everything (memory + uploaded files) — 204, no body
curl -X DELETE https://api.hrum.ai/api/v1/partners/v1/memory/member-1024 \
-H "X-Partner-Api-Key: your-api-key"
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | END_USER_NOT_FOUND | 未知の endUserId(会話の保存以外の4つのパスで共通) |
| 400 | MISSING_PARAM | 検索 — endUserId がない |
| 400 | MISSING_TAGS | 検索 — tags が空 |
| 400 | ENDUSER_ID_TOO_LONG | 会話の保存 — endUserId が255文字を超えている |
注意事項
- 1.3× の単価:メモリーをホスティングするため、入力・出力のトークン単価はAI四柱推命リーディングの1.3×です(1Mトークンあたり:入力 KRW 3,754・出力 KRW 30,030、VAT別)。
- endUserId は必須:エンドユーザーごとに一意のIDが必要です。同じIDでの呼び出しは過去の文脈を引き継ぎます。
- メモリーの保持:保存されたメモリーは、明示的に削除するまで保持されます。
四柱推命レポートAPI
ボタンひとつ、質問なしで、総評から財運・恋愛・大運まで四柱推命の全体リーディングを一度に提供します。会話型リーディングとは別の単発の有料商品です。デフォルトは専用モデル ridm/saju-report(レポートに特化したRIDM独自モデル — 単発の商品のためメモリーはありません)です。リーディングAPIのレスポンスは最大2,000文字です — より長い文章(最大12セクション、約6,000文字)が必要な場合は、このレポートAPIを使ってください。
POST /api/v1/partners/v1/reading/report
生年月日(または四柱推命の命式)を送ると、セクションごとのMarkdownで四柱推命レポートが返ります。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
| birth | object | birth または saju のいずれか | {year, month, day, hour?, minute?, gender, calendar?} — calendar: "lunar" は計算前に新暦へ変換されます。出生地・タイムゾーン・閏月(2026-10-17):万歳暦APIと同じ任意フィールド — isLeapMonth、timezone、birthLatitude、birthLongitude、country、zaSiRule、birthTimePrecision — を同じ名前・同じルールで受け付けるため、同じ出生データからは万歳暦と同じ四柱が得られます。座標は両方送ってください。片方だけ送ると 400 INVALID_LOCATION が返ります。どれも送らない場合、計算は従来どおりです(出生時刻は韓国時間、旧暦は閏月でない月として扱います)。西洋占星術の部分は、その出生時点に timezone で実際に使われていた時計時刻(夏時間を含む)と座標からチャートを作成します。birth.timezone を認識できない場合、レスポンスに warnings(field: "birth.timezone")が含まれます |
| saju | object | birth または saju のいずれか | 四柱を直接入力します:{"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}} |
| year / month / day / gender | number / string | 任意 | フラットなフィールド(旧形式、新暦)。4つすべてがそろっている場合のみ birth として受け付けます。birth も saju もない場合は 400 MISSING_SUBJECT_INPUT になります |
| hour / minute | number | 任意 | hour を省略すると時柱を除き、年・月・日の三柱でリーディングします。hour なしで送った minute は無視されます |
| tone | string | 任意 | warm(デフォルト) | casual | formal |
| candor | string | 任意 | 率直さ — t | f(デフォルト)。変わるのは長所と課題の配置と強さだけで、セクション構成や、医療・法律・投資について断定的に答えない方針はそのままです。料金はかかりません。率直さ(仮称)を参照 |
| persona | string | 任意 | 話し方・キャラクターの指示(最大2,000文字 — この長さだけが入力として課金されます) |
| sections | string[] | 任意 | セクションタイトルのリスト(1–12個、各30文字まで)。デフォルトの8つ:총평(総評)・타고난 기질(生まれ持った気質)・재물운(財運)・연애·인연(恋愛・縁)・직업·적성(仕事・適性)・올해와 내년(今年と来年)・10년 대운 흐름(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)
}
}
- 四柱推命の注入は無料:万歳暦の計算と注入、およびシステムプロンプトは課金されません。入力の課金はペルソナの長さのみで、出力は実際に使われたトークン分です。
- 実測コスト:デフォルトの8セクション(約3,000文字)のレポート1件で約85Pです(出力 ₩38,077/1M 基準)。
- 再試行は再度課金されます。同じ入力のレスポンスを再利用したい場合は、クライアント側で保存してください(べき等性)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | MISSING_SUBJECT_INPUT | birth も saju も送られていない |
| 400 | INVALID_SAJU_PILLAR | saju の柱が六十干支のいずれでもない |
| 400 | INVALID_LUNAR_DATE | 存在しない旧暦の日付 |
| 402 | INSUFFICIENT_BALANCE | レポートの最大長(6,000トークン)分の出力コストを事前に確保できなかった |
YouTube要約API
YouTube動画の字幕を取得し、要約またはQ&Aの回答を返します。字幕のない動画は400エラーを返します(課金なし)。
POST /api/v1/partners/v1/youtube/summary
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
url |
string | O | YouTubeのURL(例:https://www.youtube.com/watch?v=dQw4w9WgXcQ)または11文字の動画ID |
question |
string | 具体的な質問(任意 — ある場合はQ&Aモード) | |
maxLength |
number | 要約の目標の長さ(100–4,000、デフォルト 1,000)。出力トークンの予算として使われ、正確な文字数は保証されません | |
tone |
string | トーン:warm | casual | formal(デフォルト:casual)。質問(Q&A)モードでは無視されます | |
lang |
string | 取得する字幕の言語(デフォルト:ko)。要約(question なし)は言語にかかわらず常に韓国語で作成されます。question(Q&A)モードでは質問の言語で回答できます |
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/youtube/summary \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ", "maxLength": 1000 }'
レスポンス例
{
"success": true,
"data": {
"summary": "## 0:00~1:30 오프닝\n영상 제목 설명...\n\n## 1:30~5:00 본론\n...",
"video": {
"videoId": "dQw4w9WgXcQ",
"title": "Video Title",
"channel": "Channel Name"
},
"transcriptSource": "supadata",
"usage": {
"promptTokens": 7059,
"completionTokens": 1384
},
"costPoints": 51,
"model": "ridm/gpt-5.6-terra"
}
}
注意事項
- 字幕が必要:字幕なし → TRANSCRIPT_UNAVAILABLE 400(課金なし)。
- エラー:無効なURLまたはID 400
INVALID_YOUTUBE_URL/ 要約の生成に失敗 400LLM_GENERATION_FAILED/ 残高不足 402INSUFFICIENT_BALANCE。 - 課金:トークン単位で、使用したモデル(デフォルト
ridm/gpt-5.6-terra)の再販価格そのまま(原価 × 1.1)で課金されます — メモリー層がないため、RIDM Memoryの単価(× 1.3)は適用されません。costPoints = ceil(入力トークン × 入力単価 + 出力トークン × 出力単価)。単価は1Mトークンあたり(VAT別)です。 - 実測コスト:20–30分の動画で1回あたり約60P(トークン込み)。
- リーディングとの併用:AI四柱推命リーディングAPI(
/reading)では、tools: { "youtube": true }で質問内のリンクの字幕を注入します(トップレベルのyoutubeフィールドは無視されます)。YouTubeの注入は /reading でのみ動作します(/reading/memory は未対応)。/reading/memory に送った場合、字幕は取得されず、toolsSkippedに{"tool": "youtube", "reason": "unavailable"}が返ります。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | INVALID_YOUTUBE_URL | URLから動画IDが見つからない |
| 400 | TRANSCRIPT_UNAVAILABLE | 動画に字幕がない(課金なし) |
| 400 | LLM_GENERATION_FAILED | 要約の生成に失敗した、または空の結果が返った |
| 402 | INSUFFICIENT_BALANCE | 要約のコストを事前に確保できなかった |
| 403 | FEATURE_DISABLED | アカウントでYouTube機能がオフになっている |
機能のオン・オフ
YouTube要約APIは、パートナーアカウント単位とリクエスト単位でオプトインする方式です。アカウント全体の設定はコンソールの「機能設定」で管理します。リクエスト単位では、チャットはトップレベルの youtube:true、リーディングは tools: { "youtube": true } で有効にします。
- アカウント全体で無効:403 { code: 'FEATURE_DISABLED', feature: 'youtube' } を返します
- リクエスト単位:
youtube:trueがない、または false = YouTubeを注入しません
ドキュメント処理API
PDF、Word(.docx)、Excel(.xlsx)、PowerPoint(.pptx)、CSV、テキスト、Markdown、ハングル(.hwpx)のドキュメントをアップロードし、AIに分析させて、文脈を理解するナレッジベースに取り込みます。テキストは自動で抽出され、「AI分析」オプションをオンにすると、ドキュメントを文脈ごとのセクションに分け、セクションごとに要約と検索用タグを生成して保存します。
対応形式と制限
| 項目 | 仕様 |
|---|---|
| 対応形式 | .pdf、.docx、.xlsx、.pptx、.csv、.txt、.md、.hwpx(旧形式のハングル .hwp は非対応) |
| 最大ファイルサイズ | 10 MB |
| 抽出テキストの上限 | 200,000文字(超えた場合は charsCapped: true) |
| 1リクエストあたりの最大ファイル数 | 5(fileIds) |
| チャットへの注入サイズ | 1ファイルあたり最大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フォームでアップロードします。
リクエストフィールド
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
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 completionsまたはAIリーディングのリクエストで、fileIds パラメータを使って最大5件のドキュメントを注入します。分析済みファイルはドキュメントの要約(最大500文字)と原文を注入し、未分析のファイルは原文を注入します(原文は1ファイルあたり最大40,000文字 / 合計80,000文字。子チャンクは注入されません)。注入されたドキュメントは最後のユーザーメッセージに追加され、入力トークンとしてカウントされます。再販モデルは明示的な fileIds の注入のみに対応しています。
自動呼び出し(ridm/* のみ):ridm/* のチャットモデルとリーディング・メモリーモデルでは、ユーザーの質問とタグが重なる分析済みファイルを自動で見つけて注入します(明示的な fileIds がない場合のみ)。レスポンスでは、呼び出されたファイルIDが filesRecalled 配列に入ります。
チャットのリクエスト例
{
"model": "ridm/gpt-5.6-terra",
"messages": [
{ "role": "user", "content": "Can you summarize the main points of this document?" }
],
"fileIds": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"],
"user": "user_123"
}
レスポンス例
{
"id": "chatcmpl-abc123",
"choices": [{
"message": { "content": "문서의 주요 내용은..." },
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 2500, "completion_tokens": 150 },
"filesUsed": ["f47ac10b-58cc-4372-a567-0e02b2c3d479"]
}
filesRecalled は、ファイルが自動で呼び出された場合にのみ含まれます(空の場合は省略)。
料金と課金
- アップロードと抽出:無料(テキスト抽出にトークンは課金されません)
- AI分析(analyze=true):境界の検出+セクションごとの要約+全体の要約に実際に使われたトークンが、分析モデルの単価で課金されます。30,000文字以下は同期、30,000文字超は非同期で処理されます(status:
analyzing) - チャットへの注入:ドキュメントのテキストは入力トークンとしてカウントされ、通常のチャットリクエストと同様に課金されます
- ログ:コンソールの使用ログに
file_upload(無料)とfile_analyze(有料、実トークン)として表示されます
機能のオン・オフ
ドキュメント処理はパートナーアカウント単位で有効・無効を切り替えられます。コンソールの「機能設定」で管理し、オフの場合はすべてのファイルリクエストが403を返します。
- アカウント全体で無効:403 { code: 'FEATURE_DISABLED', feature: 'files' } を返します
- リクエスト単位:
fileIdsなし = ドキュメントを注入しません(通常どおり処理)
分析ステータスとチャンク
GET /api/v1/partners/v1/files/:id のレスポンスには analysisStatus、extractedText、chunks が含まれます。chunks は、分析が完了し totalChunks が2以上の場合にのみ配列になり(各チャンク:chunkIndex、context(要約)、最大10個のタグ)、それ以外は null です。アップロードのレスポンスには chunks はありません。
| ステータス | 説明 |
|---|---|
ready |
抽出済み、未分析(analyze=false または未指定 — analyzeRequested=false) |
analyzing |
分析中(30,000文字を超える場合は非同期) |
analyzed |
分析完了(context、tags、chunks[] を含む) |
analyze_failed |
分析失敗(理由はレスポンスに含まれません — 再度アップロードしてください) |
注意事項
- 形式のチェック:非対応の形式は 400 { code: 'INVALID_FILE_TYPE' } を返します
- その他のエラー:ファイルなし 400
FILE_NOT_PROVIDED/ 10MB超 400FILE_TOO_LARGE/ 未知のファイル 404FILE_NOT_FOUND/:idがUUIDでない場合は 400 - 分析に必要なもの:endUserId なしで analyze=true にすると 400 { code: 'END_USER_REQUIRED' } を返します
- 抽出の失敗:ドキュメントの抽出中にエラーが起きると 422 { code: 'EXTRACTION_FAILED' } を返します
- 残高チェック:分析リクエストの前にパートナーのクレジットを確認します。不足している場合は402を返します
- ナレッジベースへの自動取り込み:analyze=true の場合、各セクションの要約とタグが自動でナレッジベースに保存され、自動呼び出しの候補になります。endUserId を指定した場合は、そのユーザーのメモリー層にも追加されます。
- 再アップロード = 新しいファイル:アップロードのたびに新しいファイル(新しいid)が作成され、analyze=true の場合は再度分析・課金されます。ドキュメントは一度だけアップロードし、返されたidを
fileIdsで再利用してください。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | FILE_NOT_PROVIDED | アップロード — file パートがない |
| 400 | INVALID_FILE_TYPE | アップロード — 非対応の形式 |
| 400 | FILE_TOO_LARGE | アップロード — 10MB超(コードなしの413になる場合もあります) |
| 400 | END_USER_REQUIRED | アップロード — analyze=true なのに endUserId がない |
| 400 | (なし) | 詳細 / 削除 — :id がUUIDでない |
| 402 | INSUFFICIENT_BALANCE | アップロード — 分析コストを事前に確保できなかった |
| 403 | FEATURE_DISABLED | アカウントでドキュメント処理がオフになっている(4つのルートすべて) |
| 404 | FILE_NOT_FOUND | 詳細 / 削除 — ファイルが存在しない、または別のアカウントのもの |
| 422 | EXTRACTION_FAILED | アップロード — ドキュメントからテキストを抽出できなかった |
感情分析(Emotion)
Chat APIの要約サイクルに乗せて、ユーザーとAIの感情状態を分析します。別途LLMを呼び出すことはなく、要約プロンプトに感情ブロックを追加するだけなので、追加料金はかかりません。ridm/* モデルでのみ対応しています。
概要
有効になる条件:
- グローバル:
partner_emotion_enabled✓ - パートナー:コンソールの機能設定で「感情分析」がオンになっている
- リクエスト:
emotion: trueが指定されている - モデル:
ridm/*モデルのみ
要約の間隔(summaryEvery)
感情分析は要約サイクルごとに自動で実行されます。サイクルの間隔は summaryEvery パラメータで設定します(デフォルト:5、範囲:1–20)。
- summaryEvery=1:ほぼ毎ターン感情が更新されます(要約はレスポンスの後に非同期で実行)
- summaryEvery=5:5ターンごと(推奨)
- summaryEvery=20:20ターンごと(更新が最も少ない)
- 要約と感情のサイクルは、間隔にかかわらずパートナーに課金されることはありません。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
emotion |
boolean | 感情分析を有効にする(ridm/* モデルのみ、デフォルト:false) | |
summaryEvery |
number | 整数 1–20(デフォルト 5)。要約と感情の更新間隔(ターン数) |
リクエスト例
{
"model": "ridm/gpt-5.6-terra",
"user": "user_123",
"messages": [
{ "role": "user", "content": "Today was a rough day..." }
],
"emotion": true,
"summaryEvery": 3
}
レスポンスフィールド
| フィールドのパス | 型 | 説明 |
|---|---|---|
emotion |
object|null | 感情状態(最初のサイクルの前、または emotion=false の場合は null/省略) |
emotion.user |
object | ユーザーの感情 |
emotion.user.type10 |
string|null | 10分類の感情ラベル(joyful|calm|curious|concerned|excited|thoughtful|neutral|sad|angry|surprised|null) |
emotion.user.tone |
string|null | トーン(自由形式の文字列 — 固定リストではありません。例:"warm")または null |
emotion.user.distribution6 |
object | 6分類の分布 {joy, sadness, anger, fear, disgust, surprise}、合計 = 1000 または 0 |
emotion.assistant |
object | AIの感情 |
emotion.assistant.distribution6 |
object | AIの6分類の分布 |
emotion.trend |
string|null | 感情の傾向(improving|stable|declining|null) |
emotion.updatedAt |
ISO 8601 | 最後に感情が更新された時刻 |
emotion.turnsSinceUpdate |
number | 最後の更新からのターン数 |
レスポンス例
{
"id": "chatcmpl-xyz",
"choices": [{
"message": { "content": "오늘 하루가 힘들었군요..." },
"finish_reason": "stop"
}],
"emotion": {
"user": {
"type10": "sad",
"tone": "warm",
"distribution6": {"joy": 100, "sadness": 600, "anger": 50, "fear": 100, "disgust": 50, "surprise": 0}
},
"assistant": {
"distribution6": {"joy": 200, "sadness": 100, "anger": 0, "fear": 0, "disgust": 0, "surprise": 0}
},
"trend": "stable",
"updatedAt": "2026-08-26T12:34:56Z",
"turnsSinceUpdate": 0
},
"usage": {...}
}
分布フィールド(distribution6)
| 感情 | 値 | 説明 |
|---|---|---|
joy |
0–1000 | 喜びの強さ |
sadness |
0–1000 | 悲しみの強さ |
anger |
0–1000 | 怒りの強さ |
fear |
0–1000 | 恐れの強さ |
disgust |
0–1000 | 嫌悪の強さ |
surprise |
0–1000 | 驚きの強さ |
傾向のルール(trend)
- improving:ポジティブでない感情(sadness+anger+fear+disgust)が50以上下がった
- stable:変化が50未満
- declining:ポジティブでない感情が50以上上がった
- null:前回のサイクルのデータがない
ストリーミングのレスポンス例(SSE)
ストリーミングモード(stream: true)では、感情状態は event: message_done SSEイベントのdataに含まれます。
event: message_done
data: {"finish_reason":"stop","usage":{...},"costWon":2,"recalledMemories":[],"memorySaved":{"id":"turn-1756200000000","keywords":[]},"emotion":{"user":{"type10":"concerned","tone":"warm","distribution6":{...}},"assistant":{...},"trend":"stable","updatedAt":"2026-08-26T12:34:56Z","turnsSinceUpdate":0}}
data: [DONE]
コスト
- 追加料金なし:感情分析は要約サイクルのプロンプト内で実行され、要約と感情サイクルのトークンはパートナーに課金されません。支払うのはチャットのターン自体の入力・出力トークンのみです。
注意事項
- 最初のサイクルの前:最初の要約サイクルが実行されるまで、emotionフィールドはありません(想定どおりの動作です)。
- 機能がオフの場合:グローバルまたはパートナーの機能設定がオフのときに
emotion: trueでリクエストすると、403 { code: 'FEATURE_DISABLED', feature: 'emotion' } を返します(YouTube・ドキュメント処理と同じ)。emotionを送らないか false を送った場合は、フィールドが省略されるだけです。 - ridm/* モデルのみ対応。感情機能がオンのアカウントでは、再販(openai/*、google/*)リクエストのemotionフィールドは無視されます。オフのアカウントでは、モデルにかかわらず
emotion:trueは 403FEATURE_DISABLEDを返します。 - ストリーミング:ストリーミングのレスポンスでは、emotionは message_done SSEイベントに含まれます。
四柱推命画像API
その人の四柱推命(サジュ)の五行とエネルギーを表現するAIアートを生成します。base64エンコードのPNGで返され、料金は固定の₩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
}
}
注意事項
- 固定料金:画像の生成は1回ごとに₩200が課金されます。
- 生成時間:画像の生成には20–30秒かかります。タイムアウトは余裕をもって設定してください。
- Base64エンコード:返されるimageDataUriはbase64エンコードのPNGで、HTMLの
<img src="{imageDataUri}">タグでそのまま使えます。 - スタイル:background(背景アート)、icon(ミニマルなアイコン)、portrait(ポートレートイラスト)で変わるのは雰囲気だけです。どのスタイルもサイズは同じです(デフォルトは1024×1024の正方形)。
- タイムアウト:アップストリームが80秒以内に画像を返さない場合は 504
IMAGE_UPSTREAM_TIMEOUTが返り、課金されません。再度お試しください。 - 出生時刻が不明な場合:hour を省略すると時柱を除き、年・月・日の三柱でリーディングします。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 402 | INSUFFICIENT_BALANCE | 残高が画像1枚の料金に満たない |
| 504 | IMAGE_UPSTREAM_TIMEOUT | 80秒以内に画像を受け取れなかった(課金なし) |
画像生成API(モデル再販)
POST /api/v1/partners/v1/images/generations
GPT-ImageとNano Bananaのモデルを、1つのキーでOpenAI Images APIと同じ形式で呼び出せます。モデル・解像度・品質ごとに1枚あたりの固定料金があり、表の金額がそのまま差し引かれます(生成枚数 × 1枚あたりの料金)。プロンプトの入力トークンのコストは1枚あたりの料金に含まれ、別途加算されません。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
model | string | O | openai/gpt-image-2, openai/gpt-image-1-mini, google/nano-banana-pro, google/nano-banana, fal/nano-banana-pro, fal/nano-banana |
prompt | string | O | 生成する画像の説明(最大1,000文字)。超えた場合 → 422 PROMPT_TOO_LONG(残高の確保の後にチェックされるため、残高不足の場合は402が先に返ります)。空文字列 → 400 EMPTY_PROMPT |
size | string | GPT-Image:1024x1024(デフォルト)・1024x1536(縦長)・1536x1024(横長)・auto(モデルが選択 — その品質で最も高いサイズの料金で課金)。旧形式の値 256x256 と 512x512 は1024x1024として、1792x1024 は1536x1024として、1024x1792 は1024x1536として生成・課金されます。Nano Bananaでは比率としてのみ使われます — aspect_ratio を推奨します。 | |
quality | string | GPT-Imageのみ:low・medium(デフォルト)・high。旧形式の値 standard=medium、hd=high も引き続き使えます。Nano Bananaにlow/medium/highを送ると400を返します。 | |
aspect_ratio | string | Nano Bananaのみ:21:9・16:9・3:2・4:3・5:4・1:1(デフォルト)・4:5・3:4・2:3・9:16。比率は料金に影響しません。size より優先されます。 | |
resolution | string | Nano Bananaのみ:Nano Bananaは 1K のみ、Nano Banana Proは 1K(デフォルト)・2K・4K に対応します。Kは大文字のみです。 | |
n | number | 画像の枚数、1–4(デフォルト 1)。Googleの直接モデルは1回の呼び出しで1枚だけ生成し、1枚分だけ課金します。 |
GPT-Imageに aspect_ratio や resolution を送った場合、またはモデルが対応していない解像度をリクエストした場合は、400 INVALID_PARAMETER で拒否され、課金されません。
その他のエラー:MODEL_NOT_FOUND / INVALID_MODEL(400、未知のモデル)、INVALID_PROMPT(400、アップストリームがプロンプトを拒否)、UPSTREAM_ERROR、RATE_LIMITED(現在はHTTP 400、本文の status は429)、INSUFFICIENT_BALANCE(402)。
1枚あたりの料金(₩、VAT別)
料金を読み込み中…
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/images/generations \
-H "X-Partner-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "google/nano-banana-pro",
"prompt": "A serene mountain landscape at sunset",
"aspect_ratio": "16:9",
"resolution": "2K"
}'
レスポンス例
{
"created": 1791452814,
"data": [ { "b64_json": "iVBORw0KGgo..." } ],
"costWon": 225,
"requestId": "..."
}
- GPT-ImageとGoogleの直接モデルは画像を
b64_jsonで返し、FALモデルはurlを返します。 costWon= 1枚あたりの料金 × 実際に生成された枚数。アップストリームが画像を1枚も返さなかった場合は課金されません。- GPT-Imageのレスポンスの
usage(トークン数)は参考用で、料金計算には使われません。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | MODEL_NOT_FOUND | モデルが料金表にない |
| 400 | INVALID_MODEL | openai/、google/、fal/ 以外のプレフィックス |
| 400 | INVALID_PARAMETER | モデルが受け付けないオプション(GPT-Imageでの aspect_ratio や resolution、Nano Bananaでの quality、非対応の解像度) |
| 400 | EMPTY_PROMPT | プロンプトが空白のみ |
| 400 | INVALID_PROMPT | アップストリームのモデルがプロンプトを拒否した |
| 400 | UPSTREAM_ERROR | アップストリームのエラー、または画像0枚(課金なし) |
HTTP 400、本文の status 429 | RATE_LIMITED | アップストリームのレート制限 — 少し待ってから再度お試しください |
| 402 | INSUFFICIENT_BALANCE | 1枚あたりの料金 × n が残高を超えている |
| 422 | PROMPT_TOO_LONG | プロンプトが1,000文字を超えている |
エラーレスポンスは、他のAPIと同じ {"success": false, ...} 形式です(アンラップされるのは成功レスポンスのみです)。
時間のかかる生成 — 非同期レスポンス(202、任意)
高解像度や複数枚のリクエストは1分以上かかることがあります。リクエストヘッダー Prefer: respond-async を付けると、60秒以内に結果が出ない場合は接続を保持せず、ジョブIDとともに 202 Accepted が返り、サーバー上で最大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日のリクエスト上限にはカウントされません。APIキーごとに2秒に1回までに制限されており、それより頻繁にポーリングすると Retry-After(秒)付きで 429 IMAGE_JOB_POLL_RATE_LIMITED が返ります。レスポンスはHTTP 200で、状態は本文の status で示されます。
| status | 本文 |
|---|---|
pending | 生成中 — Retry-After ヘッダー / retryAfter の後に再度ポーリング |
succeeded | result = 同期呼び出しで返るはずだった200レスポンスそのもの(data、costWon、requestId) |
failed | error = 同期呼び出しで返るはずだったエラー本文そのもの(statusCode、code、message) — 課金なし |
- 課金:結果が出た時点で1回だけ差し引かれます。待機中は見込み額が残高から確保され、失敗またはタイムアウトの場合は確保が解除されて課金されません。何度ポーリングしても再度課金されることはありません。
- 保持期間:結果とエラーはジョブ作成から24時間取得でき、その後は削除されます(以降は404)。画像が
b64_jsonの場合、ポーリングのレスポンスも同じくらい大きくなります(画像1枚あたり数MB) — 受け取ったらすぐに保存してください。結果全体が16MBを超える場合は保存されず、ジョブはIMAGE_JOB_RESULT_TOO_LARGEで失敗します(課金なし) — 画像の枚数(n)か解像度を下げてください。 - 他のパートナーのジョブID、未知のID、期限切れのIDは、いずれも同じ 404
IMAGE_JOB_NOT_FOUNDを返します。
| HTTP | コード | 発生条件 |
|---|---|---|
| 202 | — | Prefer: respond-async のリクエストが60秒以内に終わらなかった — 上記のジョブIDでポーリング |
| 404 | IMAGE_JOB_NOT_FOUND | 未知・期限切れ、または他のパートナーのジョブID |
| 429 | IMAGE_JOB_POLL_RATE_LIMITED | 同じAPIキーで2秒以内に再度ポーリングした — Retry-After 秒待ってください |
error.statusCode 504 | IMAGE_UPSTREAM_TIMEOUT | 240秒以内に画像を受け取れなかった(課金なし) |
error.statusCode 413 | IMAGE_JOB_RESULT_TOO_LARGE | 結果が16MBを超えている(課金なし) |
error.statusCode 503 | IMAGE_JOB_INTERRUPTED | サーバーの再起動でジョブが中断された(課金なし) — リクエストを再送してください |
error.statusCode 402 | — | 結果が出た時点で残高が不足していた(課金なし) |
万歳暦API
POST /api/v1/partners/v1/manseryeok
Saju Identityを含みます — レスポンス末尾の identity フィールドには、三災(3年続く災いの周期)、神殺(象徴的な星)、空亡、根の強さ、季節の強さ、大運・年運のタイムライン、四柱推命MBTIも入ります(追加料金なし。計算に失敗した場合は null)。
万歳暦(韓国の四柱推命の暦)による命式を計算します。四柱(年・月・日・時)それぞれについて、天干と地支、漢字、五行、通変星、蔵干、納音、十二運星、神殺を求めます。節気に基づく精密な計算で、四柱推命のリーディングを一通りお届けします — 命式分析(用神(喜ぶ五行)、扶抑、調候用神、日干の強弱、清濁、通関、病薬、五行の変数)→ 10の大運(現在の大運を含み、干支の合・沖・刑・害つき)→ 5年分の年運(歳運)(年ごとの等級・関係・解釈)→ 格局と詳細解釈 → 十干論、季節の状態、空亡、虚字、飛合、暗禄 — を、トップレベルの基本フィールド30個とオプションフィールド(サブフィールドを含めて200以上)で返します。出生時刻が不明な場合、null になるのは時柱(wonkuk.hour)と、実際の時刻が必要な trueSolarTime だけです。用神・格局・日干の強弱などの分析フィールドは、年・月・日の三柱(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)。用神・格局・日干の強弱・年運などの分析フィールドは、年・月・日の三柱(6文字)から計算します。hour なしで送った minute は無視されます。 |
|
minute |
number | 出生分(0-59、デフォルト:0) | |
timezone |
string | O | タイムゾーン(例:Asia/Seoul)。必須 — 省略すると400を返します。座標を送るときの標準子午線の決定に使います。astrology: true の場合は、座標の有無にかかわらず、natalChart の出生時刻を、その時点でこのゾーンで実際に使われていた時計の時刻(夏時間を含む)として読みます。認識できない名前はデフォルトのゾーンで計算し、レスポンスに警告(UNKNOWN_TIMEZONE)が付きます |
gender |
string | O | 性別("male" または "female"、必須) |
name |
string | 氏名(任意) | |
astrology |
boolean | 任意 | true の場合、レスポンスに natalChart(太陽・月、水星から土星までのサイン)が含まれます。アセンダントは、出生時刻と出生地(birthLatitude/birthLongitude または country)もあわせて送った場合にだけ出ます。出生地がない場合、サインは正午で計算します — アセンダントの推定範囲などの詳細はネイタルチャートAPIをお使いください |
glossary |
boolean | 任意 | true の場合、この命式に出てくる用語(干支の文字、通変星、十二運星、納音、神殺、蔵干、沖・刑、地支の関係、格局、空亡、三災)の解説(title、short、body、lang の言語)がレスポンスの 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:00以降)の日柱:"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 | 命式(四柱)。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以降)。
根拠が必要な解釈にはこのフィールドをお使いください。
出生時刻が不明な場合も、年・月・日の三柱(6文字)から計算して返します。
|
ilganSummary |
string | 日干(十干論)。例:"壬水 — 큰 바다의 기운. 지혜롭고 포용력이 넓어요."(日干だけを使うため、出生時刻の有無にかかわらず返します) |
daeun |
array | 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つの地支 — 日柱が属する旬の空亡です(その地支が命式に出てくるかどうかにかかわらず常に2つ)。例:["술", "해"] |
cheonEulGwiIn |
array | 天乙貴人にあたる命式の地支。minorSinsal に "천을귀인" を含む柱の地支と同じ規則です。該当する柱がなければ []。例:["묘"] |
wolryeong |
string | 月令(節入りで決まる、その月を支配する地支)。例:"축" |
daeunNumber |
number | 大運数 — 最初の大運が始まる年齢(daeun[0].startAge、例:3)。現在の大運の番号ではありません — 現在の大運は daeun[].isCurrent で探してください |
daeunDirection |
string | 大運の向き。"순행"(順行)または "역행"(逆行) |
gyeokguk |
object|null | 格局。name('정관격' など)と summary('질서·명예·합리')。出生時刻が不明な場合も、年・月・日の三柱(6文字)から計算します |
gyeokgukDetail |
object|null | 格局の詳細解釈。primary、source、trigger、interpretation(core/career/personality/challenge)。出生時刻が不明な場合も三柱から計算します |
cheonganDetail |
object|null | 十干論の詳細。ilgan、hanja、archetype、characteristics、seasonal、relations。出生時刻が不明な場合も三柱から計算します |
hapChungReport |
object|null | 天干・地支の合・沖・刑の総合レポート:命式内の合・沖が成立するかどうかと、大運・年運によって新たにできる関係。出生時刻が不明な場合も三柱から計算します |
heojaReport |
object|null | 虚字の総合レポート。hapHeo、jaHeo、bihap、bihapEmergence、heojaGyeok、amrok。出生時刻が不明な場合も三柱から計算しますが、heojaGyeok(虚字格)は実際の時支が必要なため空になります |
gongmangDetail |
object|null | 空亡の詳細レポート。年柱・日柱による空亡、五行が空亡かどうかなど |
ohaengByeonsuHits |
array | 自動抽出した五行の変数:旺勢・制化・疏通の公式があてはまる例。各項目に key、subject(五行)、target、formula_idiom、description、category があります |
strength |
object|null | 日干の強弱のスコアと等級。dayMaster、score(-100から+100)、result('신강' 身強/'신약' 身弱)、level、breakdown(季節、助け、洩・剋、蔵干、通根)。出生時刻が不明な場合も三柱から計算します |
jeongtak |
object|null | 清濁の判定。verdict('정' 清/'탁' 濁)、reasons、severity。出生時刻が不明な場合も三柱から計算します |
tonggwan |
object|null | 通関(仲介する五行)があてはまるかどうか。複合ロジックの結果です |
byeongyak |
object|null | 病薬があてはまるかどうか。複合ロジックの結果です |
natalChart |
object|null | 西洋占星術のネイタルチャート(オプション、astrology=true のときのみ)。太陽・月、水星から土星までの7天体のサインと、アセンダント(出生地を送った場合) |
countryCodeUsed |
string|null | このレスポンスの計算に使った国コード(country を送った場合)。それ以外は null |
identity |
object|null | 常に含まれます(2026-10-10以降)。Saju Identity — rooting_hints(通根)、season_strength_hint(季節の強さ)、sinsal_list(神殺)、gongmang(空亡)、samjae(三災)、timeline(大運・年運のタイムライン)、mbti_inference(四柱推命MBTI)、coherence。計算に失敗した場合は null。Saju Identityを参照 |
ohaengDeficient |
array of string | 常に含まれます(2026-10-10以降)。ohaengBalance での数が0の五行(なければ [])。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 | 十二運星。"장생", "목욕", "관대", "건록", "제왕", "쇠", "병", "사", "묘", "절", "태", "양" のいずれか |
ungSungSub |
string(任意) | 十二運星の補足情報(任意のフィールド) |
napEum |
string | 納音の五行。例:"성두토"、"간하수"、"검봉금" |
majorSinsal |
array of string | 主な神殺。例:["장성살"]、["지살"] |
minorSinsal |
array of string | その他の神殺。例:["천을귀인", "귀문관살", "원진살", "현침살", "육해살"] |
DaeunPeriod構造(各大運)
| フィールド | 型 | 説明 |
|---|---|---|
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" になります。補正結果の形は、下の「注意事項」にある旧暦入力の例を参照してください。
注意事項
- 大きなレスポンス:万歳暦のレスポンスには、命式だけでなく大運・年運・格局・神殺などの詳細データが含まれます。必要なフィールドだけを選んでお使いください。
- オプションフィールド — 出生時刻不明時の取り決め:
hourとminuteは省略できます。hourを省略した場合、正午とは見なさず、時柱を除外します。レスポンスは次のように変わります。wonkuk.hour=null、trueSolarTime=nullohaengBalance= 年・月・日の三柱(天干+地支の6文字)から再計算branchRelationsとcheonEulGwiIn= 三柱の地支でできる項目だけが残ります- トップレベルに
birthHourが追加されます:{ known: false, hourPillar: null, basis: "three_pillars", excludedFields: [], note }。分析フィールド(yongshin、strength、gyeokguk、hapChungReport、ilganSummary、seunなど)は削除されず、三柱(6文字)から計算した値で返ります(文字数に依存するしきい値も6文字基準に換算します)。これらは正午を仮定した参考値ではなく、三柱だけから導いた値です - 出生時刻が不明かどうかは
birthHour.knownで判定してください —excludedFields.lengthではありません。この配列は現在常に空で、古いクライアントとの互換性のためだけに残しています hourなしで送ったminuteは無視されます(hourがあるときだけminute ?? 0)hourを送るリクエストにはbirthHourフィールドがなく、結果は従来どおりです(2026-10-10以降に追加されたidentityとohaengDeficientを除く)。常にhourを送る既存のクライアントには影響しません。一時的に存在した「省略時は正午で計算する」動作に合わせて作ったクライアントは、birthHour.known === falseを確認し、時柱のセルを「不明」と表示してください。strength・gyeokgukなどは常に三柱の値で返ります(2026-09-16より前は削除されていました)。相談API(/reading、/reading/memory、/reading/report)も同じ規則に従い、三柱の値をモデルに渡します
- 韓国語のフィールド値:フィールド値(天干・地支・五行など)はすべて韓国語で書かれています。
langを送ってもフィールド名は変わりません。翻訳されるのは値(用神、日干の説明、大運の向き、神殺の名前など)だけです。天干・地支・五行のコード(stem、branch、ohaeng)とohaengBalanceのキーは、どの言語でも韓国語のままです。一覧は有効な値 > 言語に依存しないコード値を参照してください。 - 追加オプションはすべて任意(2026-10-08):
lang、calendar、isLeapMonth、birthLatitude、birthLongitude、country、zaSiRule、birthTimePrecisionのどれも送らなければ、結果は従来どおりです — ただし2026-10-10以降は、レスポンスの末尾にidentityとohaengDeficientが常に追加されます(既存キーの値と順序は変わりません)。料金は引き続き ₩50/回です。 - 変更(2026-10-12):旧暦変換の基準を韓国天文研究院(KASI)のデータに切り替えたため、一部の日付で結果が変わりました。存在しない閏月は平月に変換せず、400
INVALID_LUNAR_DATEを返します。 - 旧暦入力:
calendar: "lunar"の場合、レスポンスのトップレベルに変換の詳細lunarInputが追加されます。真太陽時の補正はtrueSolarTimeに入ります。エンジンの実際の出力(旧暦 1990-07-15 14:30、釜山の座標、lang: "en"):{ "year": 1990, "month": 7, "day": 15, "hour": 14, "minute": 30, "timezone": "Asia/Seoul", "gender": "male", "calendar": "lunar", "birthLatitude": 35.1796, "birthLongitude": 129.0756, "lang": "en" } → "lunarInput": { "calendar": "lunar", "lunarDate": "1990-07-15", "isLeapMonth": false, "leapMonthApplied": false, "solarDate": "1990-09-03" }, "trueSolarTime": { "originalLocal": "14:30", "correctedLocal": "14:07", "longitudeCorrection": -23.6976, "equationOfTime": 0.3241, "totalCorrectionMinutes": -23.4, "dayShift": 0, "dstApplied": false, "basis": "coords", ... }, "ilganSummary": "辛 Metal — Jewel energy. Sharp intellect and refined aesthetic sense.", "daeunDirection": "Forward" - 入力エラー:存在しない旧暦日付(例:29日までの月の30日)は 400
INVALID_LUNAR_DATE、緯度・経度の片方だけのリクエストは 400INVALID_LOCATIONを返します。どちらも課金されません。timezoneの欠落などの形式エラーも400です(課金なし)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503など)に加えて、このAPIは次を返します:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦日付/緯度・経度の片方だけを送った(課金なし) |
| 402 | (なし) | 残高が呼び出し料金より少ない — このAPIには呼び出し前の残高チェックがないため、402はコードなしで返ります |
生涯四柱API
POST /api/v1/partners/v1/lifetime
生年月日と出生時刻から命式を計算し、その命式にあてはまる部分(日柱、日干×月支、日干×強弱、日干×用神、過不足のある五行を最大3つ、最も強い通変星のグループ)の解釈の段落を、性格・財運・仕事・恋愛・健康・人間関係・アドバイスの7つのテーマにまとめて返します。段落はHRUMの四柱推命理論で書かれており、同じ入力からは常に同じ結果が返ります。命式は万歳暦APIとまったく同じ方法で決まります。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
year · month · day | number | O | 出生年(1900-2100)・月・日(デフォルトは新暦。calendar: "lunar" で旧暦) |
hour · minute | number | 出生時刻。hour を省略すると、万歳暦APIと同じ出生時刻不明の規則(年・月・日の三柱)で計算します | |
timezone | string | O | タイムゾーン(例:Asia/Seoul)。認識できない名前はデフォルトのゾーンで計算し、レスポンスに警告(UNKNOWN_TIMEZONE)が付きます |
gender | string | O | "male" または "female" |
topic | string | 1つのテーマだけを取得する場合:personality、wealth、career、love、health、relationships、advice。省略すると7つのテーマすべて | |
lang | string | ko(デフォルト)・en・ja・th | |
layers | string[] | 追加の解釈レイヤー:"astro"(西洋占星術 — 太陽・月・アセンダントのサイン)・"ziwei"(紫微斗数 — 命宮の主星+各テーマの宮の主星)。各テーマの四柱推命の段落の後に、西洋占星術、紫微斗数の順で追加されます。省略するか [] の場合、レスポンスは今とまったく同じです | |
calendar · isLeapMonth | string · boolean | "lunar" の場合、year・month・day を旧暦の日付として読み、新暦に変換して計算します(デフォルトは "solar")。isLeapMonth: true は閏月を意味し、その年にその閏月がない場合は 400 INVALID_LUNAR_DATE(2026-10-12以降)。旧暦のリクエストでは、レスポンスに lunarInput が入ります(万歳暦APIと同じ形式) | |
birthLatitude · birthLongitude | number | 出生地の座標(両方送ってください)。四柱推命の段落と layers は同じ真太陽時の補正を使います。標準子午線は timezone の標準時(夏時間を除く)から取ります。アセンダントには出生時刻と座標の両方が必要です | |
country | string | 出生国の2文字の国コード。座標なしで KR・JP・TH を送ると、その国の代表経度で補正します(他の国は補正なし)。layers もこの国を使います(省略時は lang から推定) | |
zaSiRule | string | 子の刻(23:00以降)の日柱:"traditional"(デフォルト、翌日の日柱)・"yajaSi"(夜子時:当日の日柱。出生地補正後、23時台の時柱の天干は翌日の日干を基準にします。2026-10-20以降)。四柱推命の段落にだけ使います(紫微斗数は常に23:00で翌日に切り替わります) | |
birthTimePrecision | string | exact・approximate・estimated・unknown。出生地補正は exact のときだけ適用されます。省略した場合、座標または country を送っていれば exact として扱います |
リクエスト例
{
"year": 1990, "month": 9, "day": 4, "hour": 14, "minute": 30,
"timezone": "Asia/Seoul", "gender": "male",
"topic": "career", "lang": "ko"
}
レスポンス例
{
"success": true,
"data": {
"topics": [
{
"topic": "career",
"paragraphs": [
{ "component": "ilju", "key": "임신", "text": "..." },
{ "component": "ilgan_wolji", "key": "임_신", "text": "..." },
{ "component": "ilgan_strength", "key": "임_신강", "text": "..." },
{ "component": "ilgan_yongshin", "key": "임_화", "text": "..." },
{ "component": "ohaeng_state", "key": "목_lack", "text": "..." },
{ "component": "ohaeng_state", "key": "토_lack", "text": "..." },
{ "component": "ohaeng_state", "key": "수_lack", "text": "..." },
{ "component": "top_sipsin", "key": "인성", "text": "..." }
]
}
],
"lang": "ko",
"fallbackLanguage": null,
"engine": { "version": 1, "styleVersion": "v1" }
}
}
topicsは常に上の7テーマの順に並びます。テーマ内の段落は部分の順(日柱 → 日干×月支 → 強弱 → 用神 → 五行の状態 → 通変星のグループ)に並びます。keyは韓国語の判定値です(言語に依存しません)。ohaeng_stateの段落は命式によって0〜3個です。- 言語:リクエストした言語の段落がまだない場合、その段落だけが韓国語で返り、
fallbackLanguage: "ko"が設定されます。 - 時刻の補正:座標も
countryもない場合、入力した時刻をそのまま使います(万歳暦APIと同じ)。INTAアプリ(韓国語、時刻を直接入力)と同じ段落を得るにはcountry: "KR"を送ってください。海外で生まれた人の場合、timezoneだけでは時刻は補正されません — 座標もあわせて送ってください。 - 2026-10-11の変更:座標を送った場合、四柱推命の段落も真太陽時で補正するようになりました(以前は
layersだけが使っていました)。これにより1つのレスポンス内で四柱推命・西洋占星術・紫微斗数が同じ時刻基準にそろうため、座標を送る呼び出しでは四柱推命の段落が変わることがあります。新しいフィールドも座標も送らない呼び出しのレスポンスは変わりません。
西洋占星術と紫微斗数のレイヤー(layers)
INTAアプリの生涯四柱と同じ構成です。テーマごとに、西洋占星術は太陽・月・アセンダントのサインの段落を加え、紫微斗数は命宮(命宮)の主星の組み合わせの段落を1つ加え、続いてそのテーマを担当する宮の主星の段落を加えます — 財運(wealth)= 財帛宮(財帛)、仕事(career)= 官禄宮(官祿)、恋愛(love)= 夫妻宮(夫妻)、健康(health)= 疾厄宮(疾厄)。性格・人間関係・アドバイスのテーマには命宮の段落だけが付きます。各レイヤーの最初の段落には、画面の小見出しに使える 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= 天同+巨門。主星がない場合はempty)。ziwei_palace:テーマごとの宮の段落です。keyはpalace abbreviation_main-star abbreviation(宮の略号_主星の略号) です(wl= 財帛・cr= 官禄・sp= 夫妻・hl= 疾厄。例:cr_tj= 官禄宮、天機)。主星が2つある宮は段落が2つ、主星がない宮(空宮)は段落なしです。命宮の段落のすぐ後に来て、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/回。課金は成功した呼び出しだけで、同じ入力で繰り返した呼び出しはそれぞれ課金されます(べき等性)。 layers:実際に段落を加えたレイヤーごとに+₩20(全テーマでも1テーマでも同じ)。例:全テーマ+西洋占星術+紫微斗数 = ₩140。残高は、リクエストしたレイヤーを含む金額で事前に確認します。- 入力エラー(400)、残高不足(402)、段落の取得失敗(503
lifetime_narrative_unavailable)は課金されません。利用ログのエンドポイントはlifetimeです。 - 入力オプション:出生情報の入力は万歳暦APIと同じです(
calendar、isLeapMonth、座標、country、zaSiRule、birthTimePrecision)。万歳暦専用のオプション(astrology、glossary、name)は受け付けず、送ると400を返します(課金なし)。 - アカウントでこの機能が有効になっていない場合は 404
lifetime_not_enabled(課金なし)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503など)に加えて、このAPIは次を返します:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | lifetime_not_enabled | アカウントでこの機能が有効になっていない |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦日付/緯度・経度の片方だけを送った |
| 402 | INSUFFICIENT_BALANCE | リクエストしたレイヤーを含む金額で事前に確認したときに残高不足 |
| 503 | lifetime_narrative_unavailable | 解釈の段落を読み込めなかった(課金なし) |
紫微斗数命盤API
POST /api/v1/partners/v1/ziwei-chart
生年月日と出生時から紫微斗数(紫微斗數)の命盤を作成します。12宮(宮の名前、天干、地支、大限の年齢)、14主星と補助星(明るさと生年四化つき)、五行局、命宮・身宮の位置、生年の四化、基準日の大限と流年を返します。同じ入力からは常に同じ結果が返ります。ラベルはリクエストした言語で入り、key は言語に依存しない固定の英語値です。
計算設定(固定)
- 閏月:旧暦の閏月の1〜15日はその月、16日以降は翌月として扱います。
- 23:00〜23:59の出生:翌日の子の刻として計算します(
notes.lateZiNoticeにお知らせが入ります)。 - 年の境目:旧正月(ソルラル)。立春からソルラルまでの間の出生では、立春を使う四柱推命と年の干支が異なることがあり、その場合は
chart.yearBasisNoteにお知らせが加わります。 - 時刻の補正:四柱推命と同じ規則です。デフォルトでは入力した時刻をそのまま使います(万歳暦APIと同じ)。座標(
birthLatitude・birthLongitude)またはcountryCode(KR・JP・TH)とあわせてbirthTimePrecision: "exact"を送ると、真太陽時で補正します。結果はclockに入ります。 - 四化:三合派の星の配置+生年四化。エンジンは iztro 2.6.1 に固定しています(
chart.engine)。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
year · month · day | number | O | 出生年(1900-2100)・月・日 |
hour | number | O | 出生時(0-23)。出生時がないと紫微斗数の命盤は作れません — 省略すると 400 birth_time_required になります |
minute | number | 出生分(0-59)、省略時は0 | |
gender | string | O | "male" または "female"(大限の向きを決めます) |
calendar | string | solar(デフォルト)または lunar | |
isLeapMonth | boolean | 旧暦の閏月なら true。新暦の入力では無視されます。その年にその閏月がない場合は平月を使い、chart.lunarDate.isLeapMonth は false で返ります | |
birthTimePrecision | string | exact(真太陽時で補正)または approximate(補正なし+notes.approximateTimeNote)。省略時は補正なし | |
birthLatitude · birthLongitude | number | 出生地の座標(exact の補正用) | |
countryCode | string | 出生国、ISOの2文字コード、大文字のみ(例:KR — kr は400を返します)。座標を送らないときに代表経度で補正するのに使います | |
birthTimezoneOffset | number | 出生時刻のUTCオフセット(分、540 = KST) | |
referenceDate | string | 大限・流年の基準日、YYYY-MM-DD(デフォルト:今日、韓国時間) | |
lang | string | ko(デフォルト)・en・ja・th | |
timezone | string | 万歳暦APIとの互換用(計算には使わないため、名前を認識できなくても警告は付きません) | |
readings | boolean | true の場合、レスポンスに readings を加えます(命宮の主星の組み合わせ、7テーマ、財帛・官禄・夫妻・疾厄の各宮の主星についての段落、lang の言語)。追加 ₩20(合計₩70)。省略するとレスポンスは変わりません |
リクエスト例
{
"year": 1990, "month": 5, "day": 15, "hour": 14, "minute": 30,
"gender": "female", "referenceDate": "2026-10-08", "lang": "ko"
}
レスポンス例(一部)
{
"success": true,
"data": {
"engineVersion": 1,
"lang": "ko",
"referenceDate": "2026-10-08",
"clock": {
"inputSolarDate": "1990-05-15", "inputTime": "14:30",
"correctedSolarDate": "1990-05-15", "correctedTime": "14:30",
"correctionMinutes": 0, "dstApplied": false, "basis": null,
"hourBranch": { "key": "wei", "label": "미" }
},
"chart": {
"engine": { "name": "iztro", "version": "2.6.1", "config": { ... } },
"solarDate": "1990-05-15",
"lunarDate": { "year": 1990, "month": 4, "day": 21, "isLeapMonth": false },
"yearGanzhi": "경오",
"yearBasisNote": null,
"fiveElementsClass": { "key": "earth5", "label": "토오국" },
"soulPalaceBranch": { "key": "xu", "label": "술" },
"bodyPalaceBranch": { "key": "zi", "label": "자" },
"palaces": [
...,
{
"key": "ming", "label": "명궁",
"branch": { "key": "xu", "label": "술" },
"stem": { "key": "bing", "label": "병" },
"isBodyPalace": false,
"majorStars": [
{ "key": "ziwei", "label": "자미", "brightness": { "key": "de", "label": "득" }, "mutagen": null },
{ "key": "tianxiang", "label": "천상", "brightness": { "key": "de", "label": "득" }, "mutagen": null }
],
"minorStars": [
{ "key": "lingxing", "label": "영성", "brightness": { "key": "miao", "label": "묘" }, "mutagen": null }
],
"decadal": { "from": 5, "to": 14, "isCurrent": false }
},
...
],
"mutagens": [
{ "type": "lu", "label": "화록", "starKey": "taiyang", "starLabel": "태양", "palaceKey": "children", "palaceLabel": "자녀궁" },
{ "type": "quan", "label": "화권", "starKey": "wuqu", "starLabel": "무곡", "palaceKey": "wealth", "palaceLabel": "재백궁" },
{ "type": "ke", "label": "화과", "starKey": "taiyin", "starLabel": "태음", "palaceKey": "children", "palaceLabel": "자녀궁" },
{ "type": "ji", "label": "화기", "starKey": "tiantong", "starLabel": "천동", "palaceKey": "health", "palaceLabel": "질액궁" }
],
"currentDecadal": { "palaceKey": "children", "from": 35, "to": 44 },
"yearly": { "palaceKey": "wealth", "year": 2026 }
},
"features": [
"bright:紫微=得", "co:紫微+天相@命", "cs:命=胎", "dir:逆", "hua:祿=太陽@子女",
"lhua:忌=廉貞@流年", "limit:大限@子女", "limit:小限@辰", "ming:戌", "mingzhu:祿存",
"star:天姚@辰", "star:紫微@命", "year:庚", "yy:陽女", ...
],
"notes": { "lateZiNotice": null, "approximateTimeNote": null }
}
}
同じリクエストを "lang": "ja" で送ると、ラベルだけが変わります — 例:"yearGanzhi": "庚午"、命宮の "label": "命宮"、主星 "紫微"・"天相"、五行局 "土五局"、四化 "化禄"。
palacesは常に12項目で、地支の寅から丑までの順に並びます(寅・卯・辰・巳・午・未・申・酉・戌・亥・子・丑)。宮の種類はkeyで区別してください(ming、siblings、spouse、children、wealth、health、travel、friends、career、property、fortune、parents)。mutagensは生年の四化(禄・権・科・忌)と、四化した星がある宮の一覧です。星オブジェクトのmutagenも生年の四化です。featuresは、この命盤で成り立つ事実を紫微斗数のルールキー(<kind>:<body>、漢文のトークンを使用)で記したソート済みの文字列配列です — 1命盤あたり約1,200個、約27KB。星の位置、明るさ、生年四化、同宮、対宮、三方四正、夾(挟み)、宮の天干、五行局、命宮・身宮、納音、陰陽、大限の向き、限の宮とそこにある星に加え、命盤自体には個別に載らないもの — 補助星の位置、十二運星、小限、大限・流年の四化、命主・身主、来因宮 — も含みます。そのため、ルールの条件を単純な文字列比較で照合できます。サイズの都合で2つを除いています:3つの星の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)。- ルールの出典カードの原文引用:紫微斗数のルールカード(解釈KB、承認済みパートナーのみ)の
sourcesで、公開されている原文(パブリックドメイン版)で確認できなかった引用 —match: "PARTIAL"で原文の位置foundAtがないもの — は、原文(quote)と位置(location)を除き、"citation": "pending"(出典を確認中)付きで返します。ルールの記述とsourceIdはそのままで、原文で確認できた引用(match: "EXACT")、位置(foundAt)が確認できたPARTIALの引用、エンジンの根拠は変わりません。これにより、未確認の引用が確認済みの出典のように見えるのを防ぎます。 - 伝統版の引用(
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": "신" } },
...
]
}
}
partial には、出生時がなくても確定するものだけが返ります:生年四化の星と、年干で決まる星(禄存・擎羊・陀羅・天魁・天鉞)の地支です。宮の配置には出生時が必要なので、推測で作らないでください。このレスポンスは課金されません。
料金
- ₩50/回。
readings: trueの場合は+₩20(合計₩70)。課金は成功した呼び出しだけで、同じ入力で繰り返した呼び出しはそれぞれ課金されます(べき等性)。 - 入力エラー(400
invalid_birth_date・birth_time_requiredなど)と残高不足(402)は課金されません。利用ログのエンドポイントはziwei_chartです。 - 課金されないその他のエラー:404
ziwei_not_enabled(アカウントで機能が有効になっていない)・404ziwei_readings_not_enabled(解釈の段落が有効になっていない)・503ziwei_readings_unavailable(解釈の段落を読み込めなかった)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503など)に加えて、このAPIは次を返します:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | ziwei_not_enabled | アカウントでこの機能が有効になっていない |
| 404 | ziwei_readings_not_enabled | readings: true なのに解釈の段落が有効になっていない |
| 400 | invalid_birth_date | 存在しない新暦の日付、または範囲外の旧暦の日・閏月 |
| 400 | birth_time_required | hour がない — 上の例のように partial が一緒に返ります |
| 400 | reference_date_before_birth | referenceDate が生年月日より前 |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
| 503 | ziwei_readings_unavailable | 解釈の段落を読み込めなかった |
いずれも課金されません。
Saju Identity(万歳暦に含まれます)
2026-10-10から、Saju Identityの内容は万歳暦APIのレスポンスのidentityフィールドで返されます — 三災(3年間の災いの周期、samjae)、神殺(象徴的な星、sinsal_list)、空亡(gongmang)、通根(rooting_hints)、季節による強弱(season_strength_hint)、大運・年運のタイムライン(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:万歳暦はこの2つのパラメータを受け付けません(送ると400)。タイムラインの基準年や範囲を変える必要がある場合は、当面/identityを使い続けてください。- 通変星の名前はコード値です:
sipsin_mapの値(年・月・時の天干と地支、および日支)、たとえば비견·정관は、langにかかわらず韓国語のコード値です。表示名が必要な場合は、万歳暦のリクエストでglossary: trueを送り、返される用語集(glossary、langの言語)の訳を使ってください。一覧は有効な値 > 言語に依存しないコード値をご覧ください。 - 出生時刻が不明な場合:
/identityは正午で計算しますが、万歳暦のidentityは万歳暦本体と同じ三柱(年・月・日)を使います。/identityが三柱で計算する場合(birthHour.basis=three_pillars)、saju.hourは{ "cheongan": "", "jiji": "", "ohaeng": null }です(2026-10-16からohaengはnullで、時柱がないことを表します)。時柱は五行の集計に含まれません。 - 料金:既存の
/identityは₩10/回です(アカウントで有効な場合のみ。それ以外は404identity_not_enabled)。万歳暦のidentityには追加料金がありません。利用ログのエンドポイントはidentityです。
POST /api/v1/partners/v1/identity(旧エンドポイント)
リクエスト本文は万歳暦APIと同じで、currentYear(1900~2200)とwindowSize(1~10)が加わります。timezoneを認識できない場合は、万歳暦と同じくレスポンスにwarningsが付きます。
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/identity \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "year": 1990, "month": 5, "day": 15, "hour": 12, "minute": 0, "timezone": "Asia/Seoul", "gender": "male" }'
レスポンス例(抜粋、実際のエンジン出力)
{
"success": true,
"data": {
"saju": {
"year": { "cheongan": "경", "jiji": "오", "ohaeng": "금" },
"month": { "cheongan": "신", "jiji": "사", "ohaeng": "금" },
"day": { "cheongan": "경", "jiji": "진", "ohaeng": "금" },
"hour": { ... }
},
"sipsin_map": { "year_cheongan": "비견", "year_jiji": "정관", "month_cheongan": "겁재", ... },
"strength": { "dayMaster": "경", "score": -60, "result": "신약", "level": "중약", ... },
"rooting_hints": { ... },
"season_strength_hint": { "season": "여름", "strength_label": "최약(最弱)", ... },
"sinsal_list": [ { "id": "shinsal_haksang", "name": "학당", "name_hanja": "學堂", "category": "길신", ... } ],
"gongmang": { "sun": "갑술순", "void_branches": ["신", "유"], "hits": [] },
"samjae": { "is_in_samjae": false, "current_year_branch": "오" },
"yongshin": { "method": "조후", "primary": "수", ... },
"timeline": { "current": { "daeun": { "startAge": 27, "endAge": 37, "stem": "갑", "branch": "신", ... }, ... } },
"gyeokguk": { "primary": "비견격", ... },
"mbti_inference": { "e_i": 48, "s_n": -8, "t_f": 16, "j_p": -18, "inferred": "ESFJ", ... },
...
}
}
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | identity_not_enabled | アカウントで有効になっていない |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦日付 / 緯度と経度の片方だけを送った |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
四柱推命 ↔ MBTI比較API
POST /api/v1/partners/v1/saju-mbti
出生情報と本人のMBTIを一緒に送ると、命式(四柱、出生時刻が不明なら三柱)と、MBTIの4つの軸(E·I / S·N / T·F / J·P)ごとに四柱推命から見える傾向と入力したMBTIを並べた比較が返ります。計算のみで、LLMは使いません。料金はSaju Identityと同じ₩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に変換され、強さは「slight」として扱われます。- 強さ(
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を省くと、Saju Identityと同じ基準で計算し、birthHourを付けます。三柱基準ではwonkuk.hourはnull、pillarCountは3です。 - 注意書きルール:
caveatRuleId(R-MBTI-CAVEAT-001)とcaveatsには、これは判定ではなく現代の解釈であるという告知が入っています。結果と一緒に画面に表示してください。 - 利用ログのエンドポイント:
saju-mbti
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/saju-mbti \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{ "year": 1990, "month": 5, "day": 15, "hour": 12, "minute": 0, "timezone": "Asia/Seoul", "gender": "male", "mbti": "INFJ" }'
レスポンス例(抜粋、実際のエンジン出力)
{
"success": true,
"data": {
"wonkuk": {
"year": { "cheongan": "경", "jiji": "오", "ohaeng": "금" },
"month": { "cheongan": "신", "jiji": "사", "ohaeng": "금" },
"day": { "cheongan": "경", "jiji": "진", "ohaeng": "금" },
"hour": { "cheongan": "임", "jiji": "오", "ohaeng": "수" }
},
"pillarCount": 4,
"dayMaster": "경",
"strength": "신약",
"ohaengCount": { "목": 0, "화": 3, "토": 1, "금": 3, "수": 1 },
"ohaengState": { "목": "lack", "화": "balanced", "토": "lack", "금": "balanced", "수": "lack" },
"dominantSipseong": ["관성"],
"mbti": {
"type": "INFJ",
"source": "letters",
"axes": {
"E_I": { "value": 25, "letter": "I", "band": "slight" },
"S_N": { "value": 25, "letter": "N", "band": "slight" },
"T_F": { "value": 25, "letter": "F", "band": "slight" },
"J_P": { "value": 75, "letter": "J", "band": "slight" }
}
},
"sajuLean": {
"E_I": { "lean": "balanced", "weights": { "E": 1, "I": 1 }, "ruleIds": ["R-MBTI-OHAENG-010", "R-MBTI-STRENGTH-002"] },
"S_N": { "lean": "S", "weights": { "S": 1 }, "ruleIds": ["R-MBTI-OHAENG-006"] },
"T_F": { "lean": "T", "weights": { "T": 2 }, "ruleIds": ["R-MBTI-STEM-007"] },
"J_P": { "lean": "J", "weights": { "P": 1, "J": 2 }, "ruleIds": ["R-MBTI-OHAENG-008", "R-MBTI-SIPSEONG-002"] }
},
"comparison": [
{ "axis": "E_I", "label": "에너지 방향(E·I)", "user": "I", "userBand": "slight", "saju": "balanced", "relation": "neutral",
"text": "에너지 방향(E·I): 사주에서는 어느 한쪽으로 기우는 경향이 뚜렷하지 않아요. 입력은 I 쪽이에요." },
{ "axis": "S_N", "label": "인식 방식(S·N)", "user": "N", "userBand": "slight", "saju": "S", "relation": "different",
"text": "인식 방식(S·N): 사주와 다른 면을 키운 것으로 볼 수 있어요. 사주는 S 쪽 경향이 있고, 입력은 N 쪽이에요." },
{ "axis": "T_F", ... },
{ "axis": "J_P", "label": "생활 방식(J·P)", "user": "J", "userBand": "slight", "saju": "J", "relation": "same",
"text": "생활 방식(J·P): 사주와 같은 방향이에요. 사주에서 보이는 J 쪽 경향이 입력에도 드러나요." }
],
"matchedRules": [
{ "id": "R-MBTI-STEM-007", "statement": "庚 일간은 단단한 쇠의 기운으로 읽혀, 기준을 세워 따져 보고 결단하는 쪽(T)으로 기울기 쉬운 경향이 있어요." },
...
],
"caveats": [ { "id": "R-MBTI-CAVEAT-001", "statement": "사주와 MBTI를 잇는 이 해석은 고전 명리 이론이 아니라 현대의 해석 관행이에요. ..." }, ... ],
"caveatRuleId": "R-MBTI-CAVEAT-001",
"interim": false,
"kbStatus": "literature",
"kbVersion": "2026.10.16-2",
"engineVersion": "saju-mbti-1"
}
}
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | (本文の検証) | mbtiがない、4文字でない、軸の値が0~100の整数でない、未知のキー |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦日付 / 緯度と経度の片方だけを送った |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
| 404 | saju_mbti_not_enabled | 運営側で機能がオフになっている |
今日の運勢API
POST /api/v1/partners/v1/today
指定した日(既定:今日、韓国時間)の日柱を本人の四柱推命と照らし合わせ、1日の要約(日柱、今日の通変星、今日モードのMBTI、今年の流れのスコア、作用中の神殺(象徴的な星)、三災)と今日の運勢(日柱と日干の関係、ラッキーカラー・食べ物・キーワード、良い時間帯と避けたい時間帯、おすすめの行動、ひとことメッセージ)を返します。INTA – Life is Timingアプリのホーム画面にある「今日」カードと同じ計算です。活動との相性(taskAffinity)と1行の今日の流れ(summary.daily_flow)は常に含まれます。気温と天気を送ると今日のコーデ(fashion)が加わり、mbtiBehavior: trueを指定すると今日モードMBTIの行動パターン(mbtiBehavior)も加わります。
リクエストパラメータ
万歳暦APIと同じ出生情報とオプション(lang、旧暦日付、座標、zaSiRuleなど)を受け付けます。レスポンス内の干支・五行のコード(summary.day_master·iljuなど)は言語にかかわらず韓国語です — コード値の表をご覧ください。timezoneを認識できない場合は、万歳暦と同じくレスポンスにwarningsが付きます。さらに以下を受け付けます:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
date | string | 見る日付、YYYY-MM-DD(1900-2100)。省略すると韓国時間の今日 | |
temperatureC | number | 現在の気温(℃、−40~50)。送るとレスポンスにfashion(朝・昼・夜のコーデ)が加わります。省略するとfashionはありません(推定はしません) | |
weather | string | 天気:clear · cloudy · rain · snow · storm | |
humidity | number | 相対湿度(%、0~100)。fashion.mood(時間帯ごとの1行の天気コメント)はtemperatureC·weather·humidityの3つをすべて送ったときだけ加わります | |
mbtiBehavior | boolean | trueならsummary.today_mbtiの行動パターン(mbtiBehavior)を加えます。既定は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:1行の今日の流れ。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/回。成功した呼び出しのみ課金され、同じ入力で繰り返し呼び出すとそれぞれ課金されます(冪等性)。
- 入力エラー(400)、残高不足(402)、計算の失敗は課金されません。利用ログのエンドポイントは
todayです。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | today_not_enabled | アカウントで機能が有効になっていない |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦日付 / 緯度と経度の片方だけを送った |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
夢占いAPI
POST /api/v1/partners/v1/dream
エンドユーザーが語った夢から象徴語(例:海、魚)を見つけ、目立つ順に返します。語はHRUM独自の夢の象徴語集(日常的な名詞約1,000語と、その類義語・活用形・口語形)から取られます。語集にあるのは語だけで、夢の意味や吉凶の判定は含まれません。返される語はすべて、語そのもの、または類義語・活用形として実際に夢のテキストに現れています。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
dream | string | ✓ | 夢の内容(1,000文字まで) |
feeling | string | 夢の感じ(300文字まで、例:「무섭고 답답했어요」—「怖くて息苦しかった」)。夢のテキストと合わせてタグを抽出します(合わせたテキストの1,000文字までを使用) | |
lang | string | レスポンスの言語。現在はkoのみ対応です(辞書が韓国語のみのため)。それ以外の値は400 | |
includeNegative | boolean | 古典資料のうち、凶の判定の記録(死、病気、喪失など)を含めるかどうか。既定はfalse。古典資料が使えるようになるまでは無視されます |
リクエスト例
{
"dream": "바다에서 커다란 물고기를 두 손으로 잡는 꿈을 꿨어요"
}
レスポンス例
{
"success": true,
"data": {
"lang": "ko",
"mode": "glossary",
"items": [
{ "keywords": ["바다"], "score": 1 },
{ "keywords": ["물고기"], "score": 0.979 },
{ "keywords": ["손"], "score": 0.749 }
]
}
}
itemsは最大40件です。1件 =keywords(象徴語集の基本語1つ。例:「치아」(歯)も「앞니」(前歯)も["이빨"]になります)+score。各語は1回だけ現れます。項目は夢の中で目立つ順(早く、多く、具体的に出てくる語ほど先)に並び、scoreは0~1で、下に行くほど同じか小さくなります(1 = この夢で最も目立つ象徴)。mode:glossary(象徴語集で見つかった)·none(象徴が見つからなかった)。feelingは夢のテキストと一緒に検索されます。- 同じ入力なら同じ結果になります。外部呼び出しなしでサーバー上で直接計算します。
- 解釈の文章は含まれません。エンドユーザーに見せる解釈が必要な場合は、夢のテキストとこれらの語をAI四柱推命リーディング(
only: "dream")や自社のLLMの入力に渡してください。 - 2026-10-11の変更:旧
title·meaningフィールドは削除され、keywordsに置き換わりました。同じ日に象徴語の出典がHRUM独自の象徴語集に変わったため、各項目の語は1つになり、modeはglossary·noneの2値になりました(旧値tags·fallback_charは出なくなりました)。
料金
- ₩30/回。項目が1件以上見つかった場合のみ課金され、空の結果(
items: [])は₩0です。同じ入力で繰り返し呼び出すとそれぞれ課金されます(冪等性)。 - 入力エラー(400)と残高不足(402)は課金されません。利用ログのエンドポイントは
dreamです。
古典資料 kbMatches
夢の中のもの(空、蛇、市場など)に一致する夢解釈KBルールを返します。出典はパブリックドメインの古い夢書の原文です — 敦煌写本『周公解夢書』(周公の夢解釈書、P.3908、10世紀)と『古今圖書集成』の夢部(夢の部)。同じ夢のテキストなら常に同じ結果になります(文字一致のルールで、タグ付けサービスや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 | コード | 発生条件 |
|---|---|---|
| 404 | dream_not_enabled | アカウントで機能が有効になっていない |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
dreamが空、または1,000文字を超える場合は共通の400になります。象徴が見つからなくてもエラーではなく、items: []で200が返ります(₩0)。
顔計測・手相計測API
写真は送りません。パートナーの端末やブラウザでMediaPipeを使って抽出した座標(顔478点 / 手21点、および手相線のポリライン)を送ると、サーバーが同じ純粋関数で計測キー(比率、角度、区画)を計算し、その値に一致する人相・手相のKBルール(古い原文の記録)を返します。LLMは使わず、同じ座標なら常に同じ結果になります。座標を抽出する参考コード(ブラウザのMediaPipe、Node、curl)は参考コードのページにあります。モデル名、バージョン、正規化、点の数のいずれかが下記の値と異なると400になります。
POST /api/v1/partners/v1/face-measure
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
modelName, modelVersion | string | ✓ | 座標を出したモデル。許可リスト外:400 MEASURE_MODEL_UNSUPPORTED / MEASURE_MODEL_VERSION_MISMATCH。現在:face_landmarker · float16/[email protected] |
normalization | string | ✓ | face-norm-1 |
landmarks | number[][] | ✓ | ちょうど478個の[x, y]または[x, y, z](画像の幅・高さで割った値、−0.02~1.02) |
imageWidth, imageHeight | number | ✓ | ピクセル単位のサイズ |
hairline | [number, number] | 顔の中央の生え際の1点。サーバーは推定しません — ないと上停(顔の上部の区画)に関するキーはnullになります(理由hairline_missing)。額の上で髪が始まる位置をユーザーにタップしてもらうことをおすすめします(髪のセグメンテーションモデルは参考程度です) | |
quality | object | yawDeg·pitchDeg·rollDeg·blendshapes(MediaPipeの係数名 → スコア)。送った場合のみ品質チェックを行います | |
includeNegative | boolean | 凶の判定の記録(polarity negative)を含めるかどうか。既定はfalse(夢占いと同じ名前・意味) |
POST /api/v1/partners/v1/palm-measure
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
modelName, modelVersion | string | ✓ | 現在:hand_landmarker · float16/[email protected] |
normalization | string | ✓ | palm-norm-1 |
landmarks | number[][] | ✓ | ちょうど21個 |
imageWidth, imageHeight | number | ✓ | ピクセル単位のサイズ |
handedness | string | ✓ | left | right — 被写体の実際の手(ユーザーに選んでもらってください) |
mirrored | boolean | 左右反転した写真(自撮りプレビュー)ならtrue | |
creases | object[] | 手相線のポリライン(64本まで、1本あたり2~512点)。フィールド:points(✓)、label(life·head·heart·fate·sun·mercury·simian·unknown)、kind(segment | branch)、autoLabel。ないと線に関するキーはnullになります(creases_missing) | |
autoLabel | boolean | 名前のない線すべてに、サーバー共通のヒューリスティックで名前を付けます。1本だけに使う場合はその項目にautoLabelを指定します。自分で指定したlabelが常に優先されます | |
includeNegative | boolean | 顔と同じ。既定はfalse |
- 線の断片は送る前につなげてください。サーバーは断片をつなげず、ヒューリスティックは1本の線につき1つの断片にしか名前を付けません。別の線と交わる所で切れた断片(例:運命線と交わる感情線)は、参考コード
stitch_creases.pyのように先につなげた場合にだけ名前が付きます。実際に見える切れ目は切れたままにしてください(切れ目の数はbreaksキーで数えられます)。
リクエスト例(顔、短縮)
{
"modelName": "face_landmarker",
"modelVersion": "float16/[email protected]",
"normalization": "face-norm-1",
"landmarks": [[0.5012, 0.3121, -0.031], … 478개 …],
"imageWidth": 1080,
"imageHeight": 1350,
"hairline": [0.501, 0.182],
"quality": { "yawDeg": 2.1, "pitchDeg": -3.4, "blendshapes": { "eyeBlinkLeft": 0.05, "jawOpen": 0.02 } }
}
レスポンス例(冒頭の抜粋)
{
"success": true,
"data": {
"normalization": "face-norm-1",
"keys": { "face.thirds.upper_ratio": 0.3333, "face.brow.length_vs_eye": 1.625, "face.brow.outer_overhang": 0.1648, … },
"reasons": {},
"quality": { "rollDeg": 0, "iodPx": 158, "flags": [] },
"kbMatches": [
{
"ruleId": "R-FACE-PALACE-031",
"area": "PALACE",
"kind": "interpretation",
"polarity": "positive",
"status": "verified",
"statement": "『古今圖書集成』 相術部彙考 「十二宮訣」 兄弟는 눈썹이 눈보다 길게 지나가면(眉長過目) …라고 적는다 …",
"quote": { "text": "眉長過目,三四兄弟", "sourceId": "SRC-FACE-HUIKAO", "source": "…", "location": "…", "foundAt": "…" },
"caveatRuleIds": ["R-FACE-CAVEAT-001"],
"matchedConditions": [{ "key": "face.brow.outer_overhang", "op": "gt", "value": 0, "actual": 0.1648 }]
}
]
}
}
keys:すべての計測キー(キーの定義、計算式、信頼度はキー表のドキュメントにあります)。値を出せない場合はnullで、理由はreasonsに入ります:hairline_missing·blink·smile·jaw_open·finger_bent·creases_missing·back_of_hand(手の甲の写真 — 線に関するキーのみ)など。missingSections:値がnullの計測キーの数(キーと理由はkeys·reasonsにあります)。0ならすべてのキーが出ています。kbMatches:原文自体が数値や比較を示しているルールだけです。こちらで決めたしきい値だけで判定することになるルールは、根拠が検証されるまで除外しています(PoC)。statementは原文の内容の記録であり、予言や診断ではありません。negativeはincludeNegative: trueのときのみ。- 品質:頭が10°を超えて回転・傾いている(
MEASURE_QUALITY_POSE)または顔が小さすぎる(MEASURE_QUALITY_FACE_SIZE)場合、リクエスト全体が400になります — ユーザーに撮り直してもらってください。目を閉じている、笑っている、口が開いている場合は400にならず、影響を受けるキーだけがnullになります。 - 入力エラーはコード付きの400で返ります(
MEASURE_LANDMARK_COUNT·MEASURE_COORD_RANGE·MEASURE_COORD_NAN·MEASURE_CREASE_LIMITなど)。エラーメッセージには点のインデックスだけが入り、座標値は入りません。 - 凶の記録を表示するとき(
includeNegative: true):statementは原文の内容の記録です。ユーザーには「原文にはそういう傾向があると書かれている + こう向き合うとよい」という形で伝え、人をおとしめたり性格を決めつけたりする言葉にしないでください。
エラーコード
| HTTP | コード | 意味 |
|---|---|---|
| 400 | MEASURE_MODEL_UNSUPPORTED | modelNameが許可リストにない |
| 400 | MEASURE_MODEL_VERSION_MISMATCH | modelVersionが許可リストにない(現在はfloat16/[email protected]のみ) |
| 400 | MEASURE_NORMALIZATION_MISMATCH | normalizationがface-norm-1 / palm-norm-1でない |
| 400 | MEASURE_LANDMARK_COUNT | 点の数が顔で478 / 手で21でない |
| 400 | MEASURE_LANDMARK_SHAPE · MEASURE_COORD_NAN · MEASURE_COORD_RANGE · MEASURE_IMAGE_SIZE · MEASURE_DEGENERATE | 点の形式、数値、範囲(−0.02~1.02)、画像サイズのエラー |
| 400 | MEASURE_HANDEDNESS · MEASURE_CREASE_LIMIT · MEASURE_CREASE_SHAPE · MEASURE_CREASE_LABEL | 手または手相線の入力エラー |
| 400 | MEASURE_QUALITY_POSE · MEASURE_QUALITY_FACE_SIZE | 頭が10°を超えて回転 · 顔が小さすぎる — 撮り直してください |
| 400 | (検証エラー) | ドキュメントにないフィールドを送った — 許可されたフィールドだけを送ってください |
| 402 | INSUFFICIENT_BALANCE | クレジット残高不足 |
| 404 | face_measure_not_enabled · palm_measure_not_enabled | 機能がまだ公開されていない |
エラーレスポンスはすべて課金されません。
個人データ
- 写真は受け取りません。写真はユーザーの端末で座標に変換され、APIに届くのは座標だけです。
- 座標は保存しません。座標は顔や手の形状のため、サーバーはリクエストの処理中にメモリー上でだけ使い、ログ、データベース、エラーメッセージには残しません。利用ログに記録するのはエンドポイント、ステータス、金額だけです。
- エンドユーザーの同意はパートナー側で取得してください。
- 参考コードで使うMediaPipeはApache-2.0ライセンスで、利用統計を送信することがあります。製品に組み込む場合は、ライセンス表示を一緒に配布し、プライバシーポリシーに反映してください。
料金
- 顔計測₩30/回、手相計測₩30/回(VAT別 · VAT込み₩33)。
- 計測キーが1つ以上出た場合のみ課金されます。計測キーがなければ₩0で、入力・品質エラー(400)、残高不足(402)、未公開の機能(404)も課金されません。利用ログのエンドポイントは
face-measure/palm-measureです。 - 手相計測で写真が手の甲と判定された場合(
quality.flagsにback_of_hand)、すべてのキーがnull(理由back_of_hand)、KBルールは空になり、課金されません(₩0)。手のひら側の写真と正しいhandedness·mirroredで送り直してください。手の甲の判定は、手首・人差し指の付け根・小指の付け根の点の巻き方向をhandedness·mirroredと比べて行います。 - 一部のキーが
nullでも料金は同じです。欠けたキーの数はmissingSectionsで示されます。
人相占い・手相占いAPI(写真)
顔写真1枚から顔(人相占い)を、手のひらの写真1枚から手のひら(手相占い)を読み解きます。写真はサーバーのメモリー上でのみ扱い、保存しません。人相占いでは、写真の代わりに顔計測と同じ座標(landmarks)を送ることもできます — その場合、写真なしで計測キーとKBルールを求め、ルールごとにAIがわかりやすい解釈を書きます(人相占いには常にAIの解釈が含まれます。AIなしの計測だけが必要な場合は顔計測を使ってください)。結果は伝統的な人相・手相を娯楽・参考用に読み解いたもので、事実の判断や診断ではありません。
解釈の文章は現在韓国語のみで、別のlangを送っても韓国語で答えます(レスポンスのlangは常に"ko")。
POST /api/v1/partners/v1/face-reading
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
image | object | どちらか一方 | { data, mimeType } — dataは写真のバイト列のbase64(デコード後8MBまで)、mimeTypeはimage/jpeg · image/png · image/webp。形式はバイト列からも再確認されます(異なれば400) |
landmarks | object | どちらか一方 | 顔計測のリクエスト本文そのまま(modelName · modelVersion · normalization · landmarks 478点 · imageWidth · imageHeight · hairline · quality · includeNegative) |
consent | object | 写真なら✓ | 写真の処理への同意 — 下記の同意オブジェクトをご覧ください |
llm | boolean | 送る必要はありません — AIの解釈は常に含まれます。falseを送ると400 USE_FACE_MEASURE(AIなしの計測は顔計測) | |
lang | string | ko · en · ja · thを受け付けますが、解釈の文章は現在韓国語のみです(レスポンスのlang = "ko") | |
endUserId | string | パートナーが使うエンドユーザーID(255文字まで)。利用ログにだけ記録されます |
imageとlandmarksのどちらか一方だけを送ってください。両方送るか、どちらも送らないと400 READING_INPUT_ONE_OFになります。
リクエスト例(顔、写真)
{
"image": { "data": "/9j/4AAQSkZJRgABAQ…(base64)", "mimeType": "image/jpeg" },
"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" },
"lang": "ko",
"endUserId": "member-1024"
}
POST /api/v1/partners/v1/palm-reading
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
image | object | ✓ | 手のひら側の写真1枚。形式とサイズの制限は人相占いと同じ |
consent | object | ✓ | 同意オブジェクト |
creases | object[] | ユーザーが写真の上でなぞった手相線(16本まで)。フィールド:line(life · head · heart · fate · sun · mercury · simian · unknown)、points(2~256個の[x, y]、写真の左上からの0~1)。線の位置を特定するときに優先して使われます | |
lang | string | 人相占いと同じ(解釈の文章は現在韓国語のみ) | |
endUserId | string | 人相占いと同じ |
リクエスト例(手のひら、なぞった線あり)
{
"image": { "data": "/9j/4AAQSkZJRgABAQ…(base64)", "mimeType": "image/jpeg" },
"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" },
"creases": [
{ "line": "life", "points": [[0.42, 0.38], [0.36, 0.52], [0.34, 0.71]] },
{ "line": "heart", "points": [[0.78, 0.33], [0.6, 0.31], [0.47, 0.34]] }
]
}
同意オブジェクト consent
例:"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" }
photo:必ずtrue— ユーザーが写真の処理に同意したことを表します。version:パートナーが表示した同意文のバージョン(1~40文字)。subject:end_user(ユーザー本人の写真)·third_party(他人の写真 — パートナーはその人の同意も取得する必要があります)。- 値がない、または無効な場合は400
CONSENT_REQUIREDになります。利用ログにはversionとsubjectだけが記録されます。
写真の処理
- 写真はリクエストの処理中にメモリー上でのみ使います。ディスク、データベース、ログ、ファイルストレージには残さず、顔や手の特徴量(テンプレート、埋め込み)も作成・保存しません。誰であるかの識別や、他の写真との照合は行いません。
- 外部モデルに送る前に、EXIF(位置情報や端末情報を含む)、XMP、ICCなどのメタデータを削除し、長辺を最大1600pxにしてJPEGで再エンコードします。WebPはメタデータだけを削除してそのまま送るため、長辺1600px以下のWebPのみ受け付けます(それより大きいと413 — 縮小するか、JPEG/PNGで送ってください)。
- 写真1枚につき外部モデルを2回呼び出します。まず写真を分類し(顔または手のひらか、1人か、未成年に見えるか、画質)、通過した場合のみ解釈を書きます。どちらの呼び出しも
store: falseを使います。 - 未成年(18歳未満)に見える写真は読み解きません。複数の人や2つ以上の手が写った写真、顔や手のひらではない写真も同様です(400
IMAGE_NOT_ALLOWED)。手の甲の写真は400PALM_NOT_DETECTEDになります。手相占いでは、手のひらを1つだけ写してください。もう一方の手の指先が少し写っただけでも、2つの手と判断されて拒否されることがあります。 - 外部モデル: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
}
外部モデルを呼び出さなかったレスポンス(計測キーや一致するKB記録が見つからず₩0で終わったlandmarksの呼び出し)では、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ルールごとに1件になります。写真の解釈と同じくlabelは部位名(眉 · 目 · 鼻 …)、reasonはAIによるわかりやすい解釈で、key(計測キー)·ruleId·polarity·source(解釈の根拠となったKBルールの記述)が付きます。meta.kbRuleIdsには根拠のルールIDがまとめられます。meta.disclaimerは常にentertainment_referenceです。meta.disclaimerText(または同じ意味の文言)をユーザーの画面に表示してください。
エラーコード
| HTTP | コード | 意味 |
|---|---|---|
| 400 | READING_INPUT_ONE_OF | 顔:imageとlandmarksのどちらか一方だけになっていない |
| 400 | IMAGE_REQUIRED | 手のひら:imageがない |
| 400 | CONSENT_REQUIRED | 写真を送ったがconsentがない、または無効 |
| 400 | IMAGE_INVALID · IMAGE_FORMAT_UNSUPPORTED | 読めない写真 · mimeTypeが実際の形式と異なる · JPEG、PNG、WebPではない(アニメーションWebPを含む) |
| 413 | IMAGE_TOO_LARGE | 8MBを超える写真 · 8192pxまたは1680万画素を超える · WebPの長辺が1600pxを超える |
| 400 | IMAGE_NOT_ALLOWED | 未成年に見える · 複数の顔 / 2つ以上の手 · 顔や手のひらの写真ではない |
| 400 | FACE_NOT_DETECTED · PALM_NOT_DETECTED | 顔 / 手のひらが見つからない(手の甲の写真はPALM_NOT_DETECTED) |
| 400 | USE_FACE_MEASURE | 顔のlandmarksでllm: false — AIなしの計測は顔計測API |
| 400 | MEASURE_LOW_QUALITY | ぼやけている · 暗い · 隠れている · 小さすぎる · 傾いている — 理由はレスポンスのqualityにあります。ユーザーに撮り直してもらってください |
| 400 | CREASE_INVALID | 手相線の点が2個未満、または0~1の範囲外の点がある |
| 400 | MEASURE_* | landmarksの入力エラー(顔計測と同じコード) |
| 402 | INSUFFICIENT_BALANCE | 残高不足 — 外部モデルを呼び出す前に確認します |
| 404 | face_reading_not_enabled · palm_reading_not_enabled | 機能がまだ公開されていない |
| 409 | IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS | 同じX-Idempotency-Keyが別の本文で使われた · 同じキーの最初のリクエストがまだ処理中(下記の再試行と再送信をご覧ください) |
| 429 | FILTERED_QUOTA_EXCEEDED | 今日除外された写真が1日の上限に達した — 下記の除外された写真の1日の上限をご覧ください |
| 502 | READING_UNAVAILABLE | 解釈を作成できなかった(出力の途切れを含む) — もう一度お試しください |
| 503 | IMAGE_BUSY | 写真の処理が混み合っている — しばらくしてからもう一度お試しください |
| 504 | LLM_UPSTREAM_TIMEOUT | 外部モデルがタイムアウトした |
課金
- 料金は料金表にあります。課金されるのは200レスポンスのみで、4xx/5xxのエラーと失敗はすべて₩0です(除外された写真や、出力が途切れた502を含む)。計測キーや一致するKB記録がない
landmarksの呼び出しも₩0です。 - 利用ログのエンドポイントは
face-reading/palm-readingです。 - 写真のAPIはサーバーキーでのみ呼び出せます(アプリ専用の「AI接続」キーは403
APP_KEY_SCOPE)。写真はパートナーのサーバーを経由して送ってください。
除外された写真の1日の上限
分類の後に除外された写真(IMAGE_NOT_ALLOWED · FACE_NOT_DETECTED · PALM_NOT_DETECTED · MEASURE_LOW_QUALITY)と出力の途切れによる502は、パートナーには₩0ですが、外部モデルの費用はかかります。そのため各パートナーは、韓国時間の1日(00:00~24:00)あたり、200と、その日に成功した写真の解釈の数の3倍のうち大きい方までとなります。それを超えると、外部モデルを呼び出す前に429 FILTERED_QUOTA_EXCEEDEDで応答し(₩0、本文にfiltered · limit付き)、上限は翌日00:00(KST)にリセットされます。先にユーザーに撮影のコツ(正面を向く、明るい場所、1人だけ、手のひら側)を見せると、除外される写真が減ります。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(発音の五行、画数、81数理の4格、字義の五行、用神(喜ぶ五行)の補い)と、その値だけをもとにAIが書くinterpretationに分かれています。各計算には、根拠となった姓名判断KBルールのIDが付きます。結果は伝統的な姓名学を娯楽・参考用に読み解いたものです。
- 姓名判断(既定):計算 + AIの解釈。名前がOpenAI(米国)に送られるため、
consentが必要です。 - 姓名計算(
"interpret": false):計算のみで、AIは呼び出しません。interpretationはnullで、consentは不要です。2つは料金が異なります(料金)。 - 解釈の文章は現在韓国語のみで、別の
langを送っても韓国語で答えます(レスポンスのlang="ko")。
POST /api/v1/partners/v1/naming
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
name.hangul | string | ✓ | 2~6音節のハングルの名前、姓が先(例:김하늘)。남궁(ナムグン)、황보(ファンボ)、제갈(チェガル)、선우(ソヌ)、독고(トッコ)、사공(サゴン)、서문(ソムン)、동방(トンバン)は2音節の姓として扱います |
name.hanja | (string|null)[] | 音節ごとに漢字1文字、不明ならnull。長さが音節数と異なる場合:400 NAME_HANJA_LENGTH | |
name.strokes | (number|null)[] | 音節ごとの原画数(元の字形に基づく)(1~64)、不明ならnull(下記の画数の注記をご覧ください) | |
name.meanings | (string|null)[] | 音節ごとの漢字の意味(訓、例:물(水)· 쇠(金属)、1~20文字)。字義の五行はこの意味だけから判定します | |
birth | object | { year, month, day, hour?, minute?, gender?, timezone? }(新暦)。送ると四柱推命の用神を計算し、名前がその五行を補っているかを見ます。timezoneの既定はAsia/Seoul。生年月日は外部モデルに送りません | |
interpret | boolean | 既定はtrue(姓名判断)。falseなら姓名計算のみ(AIなし) | |
echoName | boolean | 2026-10-31追加。既定はtrue(従来どおり)。falseにすると、名前の文字をレスポンスのどこにも書き戻しません — nameはnull、deterministic.syllablesのhangul·hanja·meaningはnullになり、代わりにposition(1から)が加わります。items内の文字への言及も「첫 글자(목(木))」(「1文字目(木(木))」)のように位置に切り替わり、姓名判断では名前そのものをAIに送りません(計算値と位置だけを送ります) | |
consent | object | 姓名判断なら✓ | { "version": "name-consent-2026-10", "subject": "end_user" } — versionはパートナーが表示した同意文のバージョン(1~40文字)、subjectはend_user · third_party。値がない、または無効な場合は400 CONSENT_REQUIRED。利用ログにはversionとsubjectだけが記録されます。interpret: falseなら不要 |
lang | string | ko · en · ja · thを受け付けますが、現在は韓国語でのみ答えます | |
endUserId | string | パートナーのエンドユーザーID(利用ログのみ) |
- 画数は原画数(元の字形に基づく)で計算します(例:氵は水として4画)。サーバーが画数を知っている漢字は姓の38文字(
R-NAME-STROKE-004)だけで、そのうち辞書によって値が異なる11文字(洪·沈·河·池·鄭·郭·陳·權·禹·羅·尹)はstrokeNote: "disputed"で空欄にしています。それ以外の漢字は、name.strokesに原画数を送ると4格が得られます。1音節でも画数がなければ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(後の方が前の方を生む)。 - 81数理の
grade:good(吉)·mixed(吉凶半々)·bad(凶)。81数理の吉凶表は古典に出典のない現代の慣行です(R-NAME-MODERN-001)。 itemsはdeterministicを、他でも使われているのと同じ形(key·label·grade·score·reason·ruleId)で並べたものです。4格はすべての画数がそろっている場合にだけ含まれます。- 解釈の文章では、名前の文字を引用したり1文字ずつ取り上げたりしません(2026-10-31追加)。文字は「1文字目 · 真ん中の文字 · 最後の文字」のように位置でのみ示します。サーバーが結果を確認し、名前の文字を引用符で囲んだり名前全体を書いたりした文があれば、より厳しい指示で1回書き直します(追加料金なし)。それでも残った場合は、その部分を位置の言葉(「‘김’과」 → 「첫 글자와」、つまり「‘金’と」→「1文字目と」)や「이 이름」(「この名前」)に置き換えてから返します。引用符なしで書かれた1文字(例:助詞のように働くよくある文字)は普通の語と区別できないため、置き換えません。
"echoName": falseのレスポンス例(2026-10-31追加、短縮) — 名前を出さずに結果を表示するときに使います。"name": null, "deterministic": { "syllables": [ { "index": 0, "position": 1, "hangul": null, "hanja": null, "strokes": 8, "strokeSource": "kb", "soundElement": "wood", "meaning": null, "rootElement": "metal", ... }, { "index": 1, "position": 2, "hangul": null, "hanja": null, "strokes": 5, "soundElement": "water", "meaning": null, ... }, { "index": 2, "position": 3, "hangul": null, "hanja": null, "strokes": 7, "soundElement": "metal", "meaning": null, ... } ], ... }, "items": [ { "key": "sound_flow", "label": "발음오행 흐름", "score": 0.5, "reason": "첫 글자(목(木)) → 가운데 글자(수(水)) → 끝 글자(금(金)) · 상생 0 · 상극 0", "ruleId": "R-NAME-SOUND-011" }, ... ]
エラーコード
| HTTP | コード | 意味 |
|---|---|---|
| 400 | NAME_INVALID | ハングルの名前が2~6音節でない · hanja/strokes/meaningsの値の形式エラー |
| 400 | NAME_HANJA_LENGTH | hanjaの長さが音節数と異なる |
| 400 | CONSENT_REQUIRED | 姓名判断でconsentがない、または値が無効 |
| 400 | (検証エラー) | 存在しない日付 · ドキュメントにないフィールド |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
| 404 | naming_not_enabled | 機能がまだ公開されていない(姓名判断と姓名計算は別々) |
| 409 | IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS | 同じX-Idempotency-Keyが別の本文で使われた · 同じキーの最初のリクエストがまだ処理中(下記の再試行と再送信をご覧ください) |
| 502 | READING_UNAVAILABLE | AIの解釈を作成できなかった — 課金されません(計算だけを返す部分課金もありません)。もう一度お試しください |
| 504 | LLM_UPSTREAM_TIMEOUT | 外部モデルがタイムアウトした |
課金
- 料金は料金表にあります(姓名計算 · 姓名判断)。課金されるのは200レスポンスのみで、4xx/5xxのエラーと失敗はすべて₩0です。利用ログのエンドポイントはどちらも
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枚)から重複なくカードを引きます。カードごとに正位置/逆位置、キーワード、意味、カード画像のURLが返ります。AIによる解釈はなく、意味はそのカードに決まった固定テキストです。そのため、使い方は3通りあります。
- タロットだけでアプリを作る — レスポンスのカード名・意味・画像をそのまま画面に描画します。
- タロット+LLMによる解釈 — 引いたカードをLLM APIに渡し、独自のリーディングを書きます。
- 四柱推命AIと組み合わせる — AI四柱推命リーディングのリクエストに
tarotを加えると、四柱推命のリーディングと一緒にタロットも読み解きます(含まれるモジュール)。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
count | number | △ | 引く枚数、1~10(整数)。countとspreadはどちらか一方だけを送ります。両方送るか、どちらも送らないと400を返します |
spread | string | △ | スプレッド。それぞれ枚数とポジション名が決まっています:single(今日の1枚、1枚)・past-present-future(過去・現在・未来、3枚)・choice(選択:現状・障害・結果、3枚)・celtic-condensed(簡略版ケルト十字、5枚)・future-prediction(未来予測、5枚) |
reversed | boolean | 逆位置を許可するか(デフォルトtrue)。falseにするとすべて正位置になります | |
seed | string | 再現性のための文字列(1~200文字)。同じseed+同じcount/spread+同じreversedなら、常に同じカードを引きます。指定しない場合は毎回ランダムです(暗号論的乱数) | |
question | string | エンドユーザーの質問(最大500文字)。解釈には使われず、レスポンスにそのまま返ります — 後段のLLMに渡すための便利フィールドです | |
lang | string | カード名・キーワード・意味・スプレッド名の言語:ko(デフォルト)・en・ja・th |
リクエスト例
{
"spread": "past-present-future",
"question": "올해 하반기에 이직해도 될까요?",
"seed": "user-1042:2026-10-10"
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/tarot \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"count": 1, "lang": "en", "reversed": false}'
レスポンス例(カード1枚分を抜粋)
{
"success": true,
"data": {
"lang": "ko",
"count": 3,
"spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
"reversedAllowed": true,
"seed": "hrum-example-1",
"cards": [
{
"position": 1,
"positionLabel": "과거",
"id": "wands_10",
"name": "완드의 10",
"nameEn": "Ten of Wands",
"arcana": "wands",
"reversed": true,
"keywords": ["내려놓기", "위임", "해방"],
"meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.",
"imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp"
}
],
"cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp",
"question": "올해 하반기에 이직해도 될까요?",
"costPoints": 20
}
}
cards[]:position(1から、引いた順=スプレッドのポジション)・positionLabel(スプレッドのポジション名、countで引いた場合はnull)・id(言語に依存しないカードID)・name(リクエストした言語)・nameEn・arcana(major|wands|cups|swords|pentacles)・reversed・keywords・meaning(引いた向きのもの)・imageUrl。spread:countで引いた場合はnullです。- カード画像:
imageUrl・cardBackUrlはWebP(横幅600px)で、URLにバージョン(v2)が入っているため変わりません — 取得してキャッシュし、再利用できます。逆位置のカードは画像を180度回転して表示してください(画像はカードごとに正位置の1枚だけです)。 - 画像の出典:1909年のライダー・ウェイト版オリジナルデッキのスキャン(パメラ・コールマン・スミス、パブリックドメイン)。78枚すべてと裏面は、ウィキメディア・コモンズにある1909年オリジナルデッキのスキャンです。ファイルごとの出典とライセンスは出典台帳にあります。旧URL(
v1)も同じ画像を返すため、保存済みのURLを変更する必要はありません。 costPoints:この呼び出しで差し引かれた金額(₩)。
料金
- 1回あたり定額 — 1枚でも10枚でも同じです。価格は料金の計算API表にあります。成功した呼び出しのみ課金され、同じ入力で繰り返し呼び出すとそれぞれ課金されます(冪等性)。
- 入力エラー(400)と残高不足(402)は課金されません。利用ログのエンドポイントは
tarotです。 - 公開前に呼び出すと404
tarot_not_enabledを返します(課金なし)。
ウェイトの原典テキスト kb
公開されると、レスポンスにkbが追加されます。引いたカードごとに、A. E. ウェイト『The Pictorial Key to the Tarot』(1910年、パブリックドメイン)の原文から、そのカードの正位置・逆位置の意味を、ルールID(R-TAROT-*)と原文の引用付きで返します。上のmeaning・keywordsはそのままで、kbだけが追加され、価格も同じです。
kb.cards[]:position・id・reversed・drawn(引いた向きの意味)・upright・reversedMeaning・positionRule。各意味にはruleId・status・statement(韓国語)・quotes[](quote英語の原文、location節、foundAt原文の行)・variants[](ウェイトが挙げた別の説明はalternative、第3部§4の追加の意味はadditional)があります。statusはKBの表記をそのまま使います(verified=原文の引用あり)。ウェイトが意味を挙げていない箇所(カップの2の逆位置)はruleId: null、status: "disputed"です。method: "celtic-cross":ウェイトが同書で説明しているケルト式の占い方(10枚)。count・spreadの代わりに送ります。10個の各ポジションに対するウェイトの意味がpositionRuleに入ります。その他のspreadはウェイトの原文にない配置のため、ポジションの出典はありません(kb.method: null)。kb.caveats:意味はポジションによって変わるというウェイトの注記と、利用上の原則(占いのための道具であり、健康・法律・金銭の判断に代わるものではありません)。- 公開前に
methodを送ると404tarot_kb_not_enabledを返します(課金なし)。
{
"method": "celtic-cross",
"seed": "user-1042:2026-10-11"
}
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | tarot_not_enabled | アカウントでこの機能が有効になっていない |
| 404 | tarot_kb_not_enabled | methodを送ったが、原典テキスト機能がまだ公開されていない |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
count・spread・methodはちょうど1つだけ送ります。2つ以上、またはどれもない場合は共通の400になります。
ネイタルチャートAPI(西洋占星術) 提供終了
/astrology)をご利用ください。同じ出生情報で、10天体・ハウス・アスペクトと作成済みのリーディング文章を1回₩50の呼び出しで受け取れます。既存の/natal-chartの呼び出しは引き続き動作しますが、新規の連携にはおすすめしません。POST /api/v1/partners/v1/natal-chart
生年月日と出生時刻から、西洋占星術のネイタルチャート(太陽・月・水星・金星・火星・木星・土星の7天体の位置+アセンダント)を計算します。天王星・海王星・冥王星は含まれません。節気ではなく、西洋占星術のトロピカル方式の黄道十二宮を使います。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
birthDate |
string | O | 生年月日 YYYY-MM-DD(新暦)。実在する日付のみ(2月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になった理由(ある場合のみ。例:時刻の精度が不明、座標なし) |
ascendantHourBasis |
boolean | approximate(時単位)の時刻からアセンダントを計算した場合はtrue — 「時単位」と表示してください |
ascendantEstimate |
object|null | approximateの場合、±60分の範囲でのアセンダントの推定。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 – Life is Timingアプリの万歳暦画面と同じ文章です。以下は実際のエンジン出力です(1990-09-04 14:30、ソウルの座標、exact)。
{
"success": true,
"data": {
"sun": { ... }, "moon": { ... }, ...,
"readings": {
"dignities": [
{ "key": "Me_dom", "lang": "ko",
"text": "수성이 본궁인 쌍둥이자리나 처녀자리에 있으면 정보를 모으고 분류해 말로 옮기는 기능이 막힘없이 또렷하게 드러나요. 생각이 많아질 때 하나를 골라 끝까지 파고들면 그 명료함이 실제 성과로 이어져요." },
{ "key": "Sa_dom", "lang": "ko",
"text": "토성이 본궁인 염소자리나 물병자리에 있으면 책임을 지고 구조를 세워 반복 훈련으로 숙련을 쌓는 기능이 막힘없이 또렷하게 드러나요. 기준이 지나치게 굳어질 때 쉬어 갈 틈을 일정에 남겨 두면 그 인내가 성숙하게 쓰여요." }
],
"aspects": [
{ "key": "Me_Sa_tr", "deviation": 0.04, "lang": "ko",
"text": "수성과 토성의 트라인은 절제와 의지를 생각에 더해, 서두르지 않고 앞을 내다보며 구조를 짜는 데 힘이 실려요. 변화가 필요한 순간에 익숙한 방식만 고집할 수 있으니 새 방법도 한 번 시험해 보세요." },
{ "key": "Mo_Ma_sq", "deviation": 1.03, "lang": "ko",
"text": "달과 화성이 스퀘어를 이루면 감정이 올라오는 순간 욱하거나 규칙에 반발하는 쪽으로 기울 수 있어요. 화가 난 뒤 반응을 한 템포 늦추는 연습을 하면 그 뜨거움이 지켜야 할 것을 지키는 힘으로 바뀌어요." }
],
"lang": "ko",
"costWon": 20
}
}
}
- 出生時刻が不明な場合(
birthTimeなし、またはbirthTimePrecision: "unknown")、月の位置が大きく変わるため、アスペクトの計算から除外されます。 - リクエストした言語の文章がない段落は韓国語で返り、その
langはkoになります。 - リーディング文章を読み込めない場合:503
natal_readings_unavailable(課金なし)。
注意事項
- 料金:₩20/回(従量課金)・
readings: trueで+₩20(合計₩40) - 日付の検証:無効な日付(例:2月30日)や無効な座標/タイムゾーンは400エラーを返し、課金されません。
- アセンダントの計算:出生時刻+
birthTimePrecision(exact/approximate、省略時はexact)+緯度/経度が必要です。どれかが欠けるとascendantはnullです。 - リーディング文章のエラー:アカウントで機能が有効でないまま
readings: trueを送ると404natal_readings_not_enabled、文章の読み込みに失敗すると503natal_readings_unavailable— どちらも課金されません。 - 太陽/月/アセンダント:すべての天体と感受点はトロピカル方式の黄道十二宮(西洋占星術の標準)を使います。
- 2026-10-17の変更(
engineVersionnatal-2):birthTimeを送ってbirthTimePrecisionを省略した場合、その時刻を使うようになりました(以前は時刻を無視して正午で計算し、アセンダントはnullでした)。他のエンドポイントと同じルールです。birthTimeなし、または精度を明示した呼び出しは以前と同じ結果になります。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | natal_readings_not_enabled | readings: trueだが、リーディング文章が有効になっていない |
| 503 | natal_readings_unavailable | リーディング文章を読み込めなかった |
| 402 | (なし) | 残高が呼び出し価格より少ない — このAPIは呼び出し前の残高チェックがないため、コードなしの402が返ります |
西洋占星術トータルAPI
万歳暦と同じように、西洋占星術の計算をすべて1回の呼び出しで返します。デフォルトはネイタルチャート全体(太陽から冥王星までの10天体・月のノード・4つの感受点・ハウス(デフォルトはプラシーダス)・アスペクト・品位)です。リクエストにブロックを加えると、トランジット+セカンダリー・プログレッション(timing)と2人のシナストリー(partner)も同じレスポンスに入ります。必要な部分だけ使ってください。LLMは使いません。数値とルールキー(features)のほかに、HRUMが作成済みのリーディング文章(readings)が追加料金なしで常に付きます。INTAと同じ共通の西洋占星術エンジンで、天体の位置はNASA/JPL HorizonsとSwiss Ephemerisの基準値と照合済みです(惑星は0.005°以内)。解釈に関わるパラメータ(オーブ、アスペクトの種類、品位の表)はすべて古典資料のルールに基づいており、資料によって値が異なるもの(トランジットとプログレッションのオーブ)にはデフォルトがなく、利用者が選びます(下記「デフォルトと選ぶ必要がある値」を参照)。
POST /api/v1/partners/v1/astrology
出生情報はネイタルチャートAPIと同じです(birthDate・birthTime・birthTimePrecision・birthLatitude・birthLongitude・birthTimezoneOffset、デフォルト540=KST。韓国の夏時間と1954~61年のUTC+8:30期間は自動で反映されます)。birthTimePrecisionを省略するとunknown(正午基準)です。
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
houseSystems | string[] | placidus・whole_sign・equal・porphyryから任意。省略すると["placidus"]。極圏内の出生地(緯度が約66.56°を超える、angles.polar)では、プラシーダスの代わりにポルフィリーで計算し、結果に"fallbackFrom": "placidus"が付きます(プラシーダスを明示的にリクエストした場合も同じです) | |
minorAspects | boolean | セミセクスタイル(30°)・セミスクエア(45°)・セスキコードレート(135°)・クインカンクス(150°)を含めます(ネイタルとシナストリー)。デフォルトfalse — メジャーアスペクト5種のみ | |
orbs | string | ネイタルとシナストリーのオーブ表:leo1928(デフォルト — コンジャンクション/オポジションは太陽–月12°、太陽・月–惑星10°、惑星–惑星8°、スクエア/トライン8°、セクスタイル7°、セミスクエア/セスキコードレート4°、セミセクスタイル/クインカンクス2°)・heindel1919(メジャーは一律6°、保守的) | |
node | string | ルールキーのNn(ノースノード)とSn(サウスノード=ノースノード+180°)がどちらのノードに従うか:mean(デフォルト、平均ノード)・true(真ノード)。featuresのnode_sign Nn_…・Sn_…と、ノードのコンジャンクションキー(Mo_Nn_cj・Nn_Asc_cjなど)に適用されます。MNn_…・TNn_…のキーはこの値に関係なく両方返ります | |
lang | string | signName(サイン名)の言語 — ko(デフォルト)・en・ja・th | |
timing | object | 送るとトランジット+セカンダリー・プログレッションを計算し、レスポンスのtimingに入れます。下の表を参照 | |
partner | object | 相手の出生情報(lang以外は上と同じフィールド)。送ると、2人の間のアスペクトとサインの関係がレスポンスのsynastryに入ります。相手の出生時刻と座標(birthLatitude・birthLongitude)があれば、相手のアセンダント(Asc)とMC(ミッドヘブン)も計算し、クロスアスペクトに含めます |
timingブロックの中身:
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
orbDegrees | number | O | トランジット→ネイタル、プログレス→ネイタルのアスペクトのオーブ(度)、0.5~10。すべての天体の組み合わせに同じ値を使います(メジャーアスペクト5種のみ) |
at | string | 見る時点。YYYY-MM-DD(=その日のUTC 00:00)またはオフセット付きの日時(2026-10-11T09:00:00+09:00、...Z)。オフセットのない日時は400を返します。省略すると現在 | |
progressions | boolean | セカンダリー・プログレッションを計算するか(デフォルトtrue) | |
yearLength | string | 経過時間を「年齢(年)」に換算するときの1年の長さ:tropical(365.24219日、デフォルト)・julian(365.25日) |
リクエスト例1 — デフォルト(ネイタルのみ)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["placidus", "whole_sign"]
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "birthLatitude": 37.5665, "birthLongitude": 126.978, "minorAspects": true, "lang": "en"}'
レスポンス例1(抜粋、実際のエンジン出力)
{
"success": true,
"data": {
"natal": {
"utc": "1990-05-15T05:30:00.000Z",
"timePrecision": "exact",
"timeKnown": true,
"zodiac": "tropical",
"lang": "ko",
"bodies": [
{ "id": "Sun", "longitude": 54.1347, "sign": "Taurus", "signKey": "tau", "signName": "황소자리", "degreeInSign": 24.1347, "speed": 0.9643, "retrograde": false, "dignities": [], "house": { "placidus": 9, "whole_sign": 9 } },
{ "id": "Moon", "longitude": 293.8244, "sign": "Capricorn", "signKey": "cap", "signName": "염소자리", "degreeInSign": 23.8244, "speed": 12.2943, "retrograde": false, "dignities": ["det"], "house": { "placidus": 4, "whole_sign": 5 } },
...
],
"nodes": [
{ "id": "MeanNode", "longitude": 311.3535, "sign": "Aquarius", "signName": "물병자리", "speed": -0.0529,
"south": { "longitude": 131.3535, "sign": "Leo", "signName": "사자자리", ... } },
{ "id": "TrueNode", ... }
],
"angles": { "asc": 173.5996, "mc": 82.8067, "dsc": 353.5996, "ic": 262.8067,
"ascSign": { "sign": "Virgo", "signName": "처녀자리", ... }, "mcSign": { ... }, "dscSign": { ... }, "icSign": { ... }, "polar": false },
"anglesOmitted": null,
"houseSystems": ["placidus", "whole_sign"],
"houses": {
"placidus": { "cusps": [173.5996, 199.6989, 229.8749, ...], "bodies": { "Sun": 9, "Moon": 4, "Jupiter": 10, ... } },
"whole_sign": { "cusps": [150, 180, 210, ...], "bodies": { "Sun": 9, "Moon": 5, ... } }
},
"housesExcluded": [],
"orbs": "leo1928",
"minorAspects": false,
"aspects": [
{ "a": "Jupiter", "b": "Uranus", "type": "opposition", "code": "op", "key": "Ju_Ur_op", "separation": 179.6986, "orb": 0.3014, "orbLimit": 8, "strength": "exact", "applying": false, "outOfSign": false },
{ "a": "Sun", "b": "Moon", "type": "trine", "code": "tr", "key": "Su_Mo_tr", "orb": 0.3104, "orbLimit": 8, "strength": "exact", "applying": true, "outOfSign": false },
...
],
"dignities": { "Sun": [], "Moon": ["det"], "Mercury": [], "Venus": ["det"], "Mars": [], "Jupiter": ["exa"], "Saturn": ["dom"] },
"moonSignUncertain": false,
"features": [
{ "type": "planet_sign", "key": "Su_tau" },
{ "type": "dignity", "key": "Mo_det" },
{ "type": "planet_retrograde", "key": "Me_rx" },
{ "type": "planet_house", "key": "Su_h9", "system": "placidus" },
{ "type": "aspect", "key": "Su_Mo_tr", "strength": "exact", "applying": true, "orb": 0.31 },
{ "type": "meta", "key": "time_known" },
...
]
},
"readings": {
"dignities": [
{ "key": "Mo_det", "text": "달이 염소자리에서 손상 자리에 있으면 감정을 바로 내보이기보다 책임과 일의 질서 속에서 조심스럽게 다루는 경향이 있어요. ...", "lang": "ko" },
{ "key": "Ve_det", ... }, { "key": "Ju_exa", ... }, { "key": "Sa_dom", ... }
],
"aspects": [
{ "key": "Su_Mo_tr", "text": "태양과 달의 트라인은 의지와 정서가 같은 곳을 바라봐, 스스로 길을 내며 생활 전반을 고르게 꾸려 가는 힘이 실려요. ...", "lang": "ko", "deviation": 0.31 },
{ "key": "Su_Sa_tr", ... }, { "key": "Mo_Sa_cj", ... }, ...
],
"lang": "ko"
},
"readingsUnavailable": false,
"costPoints": 50
}
}
timing・partnerを送らない場合、レスポンスにtiming・synastryキーは一切ありません。
bodies[]:太陽・月・水星・金星・火星・木星・土星・天王星・海王星・冥王星。longitudeは黄経(0°=春分点、トロピカル)、speedは度/日 — 負の値はretrograde: trueを意味します。各天体にはsignName(langの言語のサイン名)・degreeInSign(サイン内の度数、0~30°)・house(リクエストしたハウス方式ごとのハウス番号、houses[system].bodiesと同じ値 — ハウスを計算しない場合は{})が付くので、これだけでチャート表を描けます。dignities:太陽から土星までの品位(dom本宮・exa高揚・det損傷・fal失墜、該当する状態すべて)。bodies[].dignitiesと同じ値です。nodes[]:MeanNode(平均ノード)・TrueNode(真ノード)=ノースノード、south=サウスノード(+180°)。angles:ASC・MC・DSC・IC。出生時刻(exact/approximate)と座標が両方ある場合のみ計算されます。それ以外はnullで、anglesOmittedに理由(time_unknown|coordinates_missing)が入ります。この場合ハウスも計算されず、housesは{}です。houses:リクエストした方式ごとに、cusps(1~12ハウスの開始黄経)+bodies(天体ごとのハウス番号)。houseSystems・houses:実際に計算した方式。極圏内の出生地(angles.polar=緯度が約66.56°を超える)ではプラシーダスが定義できない場合があるため、代わりにポルフィリーで計算し、houses.porphyry.fallbackFrom = "placidus"で示します(黙って切り替えることはありません)。判定には出生地の緯度を使うため、同じ出生地なら時刻に関係なく常に同じ方式になります。housesExcludedには、計算できなかったその他の方式が理由とともに入ります(エラーレスポンスではありません)。aspects[]:orb=正確な角度からのずれ(度)、strength=exact(2°以内)・close(上限の半分以内)・wide、applying=正確な角度に近づいていればtrue(不明ならnull)、outOfSign=サインの境界をまたぐアスペクト(1段階弱く読みます)。moonSignUncertain:時刻が不明な場合、その日のうちに月がサインを移るならtrue— このときfeaturesの月のplanet_signに"uncertain": trueが付きます。readings(常に含まれ、追加料金なし):HRUMが作成済みのリーディング文章。dignities[]=品位(太陽から土星まで、天体ごとに最も強い状態1つ)、aspects[]=ネイタルの天体同士のアスペクトで、オーブの狭い順。各段落にはkey(features・aspects[].keyと同じキー)・text・lang(段落の実際の言語 — リクエストした言語の段落がなければko)・deviation(アスペクトのみ、正確な角度からのずれ(度))があります。作成済みの段落があるキーのみ含まれ、それ以外は省かれます(その場で書くことはありません) — 天王星・海王星・冥王星が関わるアスペクトとマイナーアスペクトには段落がなく、省かれます。出生時刻がない場合、月が関わるアスペクトは含まれません。月のサインが確定しない場合、月の品位は含まれません。上の例(1990-05-15 14:30、ソウル)は16個のアスペクトのうち7個+品位4個=11段落です。readingsUnavailable:リーディング文章を読み込めなかった場合はtrue— チャートの計算はそのまま返り、readingsは空の配列になり、価格(₩50)は変わりません。features[]:ルールデータベースと照合するためのキー。planet_signSu_ari・planet_retrogradeMe_rx・dignityMa_dom・node_signMNn_leo・TNn_leo・Nn_leo・Sn_aqu(Nn・Snはnodeオプションで選んだノード)・angle_signAsc_sco・planet_houseVe_h7(+system)・aspectSu_Mo_cj(ノードはコンジャンクションのみ、3° —Mo_Nn_cj・Sa_Sn_cj・Nn_Asc_cj。アセンダントとの組み合わせは出生時刻がある場合のみ)・house_cusp_signh12_ari(12ハウスのカスプが牡羊座)・house_emptyh6(10惑星のどれもないハウス)・house_ruler_househ1_h7(1ハウスの支配星が7ハウスにある)・house_ruler_signh7_lib(7ハウスの支配星が天秤座にある) — ハウスの支配星はカスプのサインの伝統的な支配星(太陽から土星までの7惑星)・planet_risingJu(1ハウス、またはアセンダントから6°以内の12ハウスにある) — この5種類は+systemが付き、出生時刻と座標がある場合のみ出ます・planet_solarVe_cazimi(太陽から17′以内)/Me_combust(17′~8°30′、太陽と同じサイン)/Ma_beams(それ以外で17°以内) — 3段階は重なりません・moon_phasewaxing・waning・metatime_known(時刻あり —exact・approximate)/time_hour_level(approximateの場合に追加)/time_unknown。アスペクト系のキー(aspect・transit・progressed・syn_aspect)にはorb(正確な角度からのずれ(度)、小数点以下2桁)と、アスペクトがサインの境界をまたぐ場合のみ"outOfSign": trueが付きます — ルールキーの属性[orb=…]・[outOfSign=true]と照合するための値です。出生時刻が不明な場合、月が関わるネイタルのアスペクトには"uncertain": trueが付きます。天体の略号Su Mo Me Ve Ma Ju Sa Ur Ne Pl、ノードMNn TNn Nn Sn、アスペクトのコードcj(0°)sx(60°)sq(90°)tr(120°)op(180°)・マイナーssx(30°)ssq(45°)sqq(135°)qcx(150°)。
リクエスト例2 — timing付き(トランジット+セカンダリー・プログレッション)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["whole_sign"],
"timing": { "at": "2026-10-11T09:00:00+09:00", "orbDegrees": 3, "yearLength": "tropical" }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "timing": {"orbDegrees": 2, "progressions": false}}'
レスポンス例2(抜粋。natalは例1と同じ形)
{
"success": true,
"data": {
"natal": { ... },
"timing": {
"at": "2026-10-11T00:00:00.000Z",
"orbDegrees": 3,
"natalPoints": ["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Asc", "MC"],
"transits": {
"bodies": [ { "id": "Sun", "longitude": 197.6966, "sign": "Libra", "signName": "천칭자리", "speed": 0.9889, "retrograde": false, ... }, ... ],
"aspects": [
{ "a": "Mars", "b": "Mercury", "type": "square", "key": "tMa_nMe_sq", "orb": 0.6358, "orbLimit": 3, "strength": "exact", "applying": true, "outOfSign": false },
...
]
},
"progressions": {
"yearLength": "tropical",
"yearLengthDays": 365.24219,
"ageYears": 36.4081,
"instant": "1990-06-20T15:17:39.048Z",
"bodies": [ { "id": "Sun", "longitude": 89.0352, "sign": "Gemini", "signName": "쌍둥이자리", ... }, ... ],
"aspects": [
{ "a": "Uranus", "b": "Mercury", "type": "trine", "key": "pUr_nMe_tr", "orb": 0.0862, "orbLimit": 3, "strength": "exact", "applying": false, "outOfSign": false },
...
]
},
"features": [
{ "type": "transit", "key": "tMa_nMe_sq", "strength": "exact", "applying": true, "orb": 0.64 },
{ "type": "progressed", "key": "pUr_nMe_tr", "strength": "exact", "applying": false, "orb": 0.09 },
...
]
},
"readings": { ... }, "readingsUnavailable": false,
"costPoints": 50
}
}
- トランジットの対象(
natalPoints):ネイタルの10天体と、出生時刻と座標があればアセンダント(Asc)とミッドヘブン(MC)。キーには接頭辞t(トランジット)とn(ネイタル)を使います —tSa_nSu_cj=トランジットの土星がネイタルの太陽とコンジャンクション。 transit_housetSa_h7(トランジットの土星がネイタルの7ハウスにある)・progressed_housepMo_h4(プログレスの月がネイタルの4ハウスにある):それぞれ10惑星。ネイタルのハウスはデフォルトの方式(プラシーダス。極地ではポルフィリー+"fallbackFrom": "placidus")を使い、キーには"system"が付きます — 別のhouseSystemsを送っても、この2つのキーはデフォルトの方式を使います。出生時刻または座標がない場合は出ません。- プログレス→ネイタルのアスペクトは、ネイタルの惑星のみが対象です。キー
pSu_nJu_tr=プログレスの太陽がネイタルの木星とトライン。instantはプログレスのチャートに使った空の時点です(出生+ageYears日)。 progressions: falseの場合、timing.progressionsはnullです。yearLengthを省略するとtropical(365.24219日)です。progressionsがオンのとき、出生時刻より前のtiming.atは400at_before_birthを返します(課金なし)。- 時刻が不明な場合、ネイタルチャートは正午で設定されます。ネイタルの月を対象とするキー(
…_nMo_…)とプログレスの月のキー(pMo_…)には"uncertain": trueが付きます(プログレスの月はネイタルの月の位置を受け継ぐため、正午の仮定の分だけずれます)。
リクエスト例3 — partner付き(シナストリー)
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"birthTimePrecision": "exact",
"birthLatitude": 37.5665,
"birthLongitude": 126.978,
"houseSystems": ["whole_sign"],
"partner": { "birthDate": "1992-11-03", "birthTime": "08:10", "birthTimePrecision": "exact", "birthLatitude": 35.1796, "birthLongitude": 129.0756 }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "partner": {"birthDate": "1992-11-03"}}'
レスポンス例3(抜粋。natalは例1と同じ形)
{
"success": true,
"data": {
"natal": { ... },
"synastry": {
"partner": {
"utc": "1992-11-02T23:10:00.000Z",
"timePrecision": "exact",
"timeKnown": true,
"moonSignUncertain": false,
"bodies": [ { "id": "Sun", "longitude": 220.7903, "sign": "Scorpio", "signName": "전갈자리", "speed": 1.0016, "retrograde": false, "dignities": [], ... }, ... ],
"angles": { "asc": 252.31, "mc": 175.86, "ascSign": { "sign": "Sagittarius", "signName": "사수자리", ... }, "mcSign": { "sign": "Virgo", "signName": "처녀자리", ... } },
"anglesOmitted": null
},
"orbs": "leo1928",
"minorAspects": false,
"aspects": [
{ "a": "Moon", "b": "Mars", "type": "opposition", "code": "op", "key": "aMo_bMa_op", "orb": 0.2993, "orbLimit": 10, "strength": "exact", "applying": null, "outOfSign": false },
{ "a": "Neptune", "b": "Uranus", "type": "conjunction", "code": "cj", "key": "aNe_bUr_cj", "orb": 0.3898, "orbLimit": 8, "strength": "exact", "applying": null, "outOfSign": false },
...
],
"features": [
{ "type": "syn_aspect", "key": "aMo_bMa_op", "strength": "exact", "orb": 0.3 },
{ "type": "syn_aspect", "key": "aNe_bUr_cj", "strength": "exact", "orb": 0.39 },
{ "type": "astro_syn", "key": "Su_Mo_se" },
{ "type": "syn_sign", "key": "aAsc_bAsc_es" },
...
]
},
"readings": { ... }, "readingsUnavailable": false,
"costPoints": 50
}
}
- キーの接頭辞:
a=リクエストした本人、b=partner。aVe_bMa_cj=本人の金星が相手の火星とコンジャンクション。本人の10天体(+アセンダント、MC)×相手の10天体(+アセンダント、MC)のすべての組み合わせを調べます(向きを区別するため、aSu_bMoとaMo_bSuは別のキーです)。 - アセンダント(
Asc)とミッドヘブン(MC)は、その人の出生時刻と座標が両方ある場合のみ計算されます(本人と同じルール。相手についてはsynastry.partner.angles/anglesOmittedを参照)。感受点が関わるクロスアスペクトはコンジャンクションとオポジションのみ、6°で調べます。唯一の例外はアセンダント同士のコンジャンクション(aAsc_bAsc_cj)で、17°まで認めます(プトレマイオス『テトラビブロス』 — 2人のアセンダントが17°以内なら強い結びつき、ルール[orb=17])。実際の離角はorbに入ります。感受点は、その感受点を持つ人の時刻がわかっていれば計算されます。ディセンダントとICはアセンダントとMCのちょうど反対なので、別のキーはありません。 astro_syn:古典的な6つの組み合わせ(太陽–月、金星–火星、月–金星、太陽–金星、月–火星、金星–土星)のうち、最も強いサインの関係2つ。両方向は1つのキーにまとめます(Su_Mo_se=一方の太陽ともう一方の月が同じエレメント)。syn_sign:本人のすべてのポイント×相手のすべてのポイントのサインの関係(aAsc_bAsc_ss)。2人とも出生時刻がexactなら、パート・オブ・フォーチュン(PoF、昼夜で計算式を反転)もポイントとして含まれます(aPoF_bPoF_ss) — パート・オブ・フォーチュンはアセンダントとともに約4分で1°動くため、時単位(approximate)や不明な時刻では出しません。関係のコード:ss(同じサイン)・op(反対のサイン)・se(同じエレメント)・es(支え合うエレメント)・sm(同じクオリティ)・ef(エレメントの摩擦)・nt(無関係)。- オーブ表とマイナーアスペクトの設定は、ネイタルチャートと同じ
orbs・minorAspectsを使います。2つのネイタルチャートの間には接近・分離がないため、applyingは常にnullです。 - どちらかの出生時刻が不明な場合、その人のチャートは正午で設定されます。その人の月が関わるアスペクトには
featuresで"uncertain": trueが付きます(月は1日に約13°動き、オーブより大きいため)。相手の感受点と組むアスペクト(aAsc_bMo_…、逆方向のaMo_bAsc_…)も同様です。 - 相手のハウスは計算しません(シナストリーのハウスオーバーレイは提供していません)。
デフォルトと選ぶ必要がある値
- ハウス方式(デフォルト
placidus):1819年と1929年の辞典が「一般に使われている」と説明している方式です。極地ではポルフィリーに置き換え、fallbackFromで示します。別の方式が必要ならhouseSystemsで選んでください。 - プログレッションの1年の長さ(デフォルト
tropical、365.24219日):原典の「誕生日から次の誕生日まで」の1年です。ユリウス年(julian)との差は、80歳でプログレスの時刻にして約2.5分です。 - トランジットとプログレッションのオーブ(
timing.orbDegrees、timingを送る場合は必須):資料によって異なります(正確な角度の前8°から10°までの幅)。空のままにすると400を返します。 - 冥王星・ノード・感受点が関わるネイタルのアスペクトはデフォルトのオーブ表にありません:Leo(1928)とHeindel(1919)のオーブ表が扱っていないポイントです(冥王星の発見は1930年)。そのため、これらのポイントはネイタルの
aspectsには出ません(位置とハウスには出ます)。シナストリーで感受点のクロスアスペクトだけを、コンジャンクション/オポジション6°で調べます(アセンダント同士のコンジャンクションのみ17°)。
提供していないもの
- マイナーな品位(トリプリシティ・ターム・フェイス)、レセプション、ネイタルのパート・オブ・フォーチュン(シナストリーの
syn_signでのみ使用)、天王星・海王星・冥王星の品位、パラレルとミッドポイント - プログレスの感受点(プログレスのASC・MC) — 原典に方法が定義されていません
- DSC・ICの値は返しますが、
featuresのキーは出しません(サウスノードはSnキーで出ます) - 新月・満月・上弦・下弦の月相キー(
moon_phaseはwaxing・waningのみ)、太陽に対するオリエンタル/オクシデンタル、プログレスの感受点のキー - シナストリーのハウスオーバーレイ
料金
- 1回₩50、万歳暦と同じ —
timing・partnerブロック、ハウス方式、マイナーアスペクトを加えても変わらず、課金は₩50の1回です。レスポンスのcostPointsは差し引かれた金額(₩)です。利用ログのエンドポイントはastrologyです。 - 計算が成功した場合のみ差し引かれます。入力エラー(400)と残高不足(402)は課金されません。
- 公開前に呼び出すと404
astrology_not_enabledを返します(課金なし)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | astrology_not_enabled | アカウントでこの機能が有効になっていない |
| 400 | at_before_birth | timing.atが出生時刻より前(プログレッションがオンの場合) |
| 402 | (なし) | 残高が呼び出し価格より少ない — このAPIは呼び出し前の残高チェックがないため、コードなしの402が返ります |
運勢フローAPI
1人の四柱推命から、大運・年運(歳運)・月運が命式にどう重なるかを計算し、グラフ用の数値と関係の一覧を返します。1回の呼び出しで1人、LLMは使いません。縦軸の値は「運の文字を加えた日干側のスコア」です — 命式の強弱の合計スコアに、運の文字ごとに命式と同じ文字別の表(生扶・剋洩・蔵干・通根)で採点した分を加え、±100で切り詰めます。運の良し悪しを測るものではありません(R-SAJU-UN-034)。身強・中和・身弱(日干の強弱)のラベルは命式のもので、運によって付け直されることはありません。
料金:1回₩50(万歳暦と同じ。範囲を広げても月運を加えても同じ価格)。400などの失敗レスポンスは課金されません。
数値はすべてINTAと同じ共通の四柱推命エンジンから出ています。出生時刻は韓国標準時の時計時刻の履歴(1954~61年のUTC+8:30、夏時間は自動で反映)として読み、節入りの時刻と比べるため、サーバーのタイムゾーンに関係なく結果は同じです。
出生地(2026-10-15追加、saju-flow-5):万歳暦APIと同じフィールド(birthLatitude・birthLongitude・country・birthTimePrecision)を受け付け、同じ方法で真太陽時の補正を適用します。出生時刻が時柱・日柱・節気の境目に近いと、補正によって命式の文字が変わるため、万歳暦に送ったのと同じ位置を運勢フローにも送り、両方の結果が同じ命式を使うようにしてください。位置がない場合は、位置なしで万歳暦を呼び出したときと同じデフォルト処理(現在は補正なし)を使い、そのデフォルトをレスポンスのassumedLocationで示します。
POST /api/v1/partners/v1/saju-flow
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
birthDate | string | O | YYYY-MM-DD(1900~2100)。指定したcalendarでの日付 |
birthTime | string | null | HH:mm。ない場合は時柱が不明 — 6文字で計算し、hourKnown: false | |
calendar | string | O | solar・lunar(旧暦の日付は新暦に換算して計算) |
isLeapMonth | boolean | 旧暦の閏月(デフォルトfalse) | |
gender | string | null | male・female。ない場合は大運の層がありません(daeun: []、daeunIndex: null) | |
timezone | string | Asia/Seoulのみ受け付けます | |
birthLatitude · birthLongitude | number | 出生地の座標(両方送る必要があります)。万歳暦APIと同じフィールドとルール — 経度を真太陽時の補正に使い、運勢フローは万歳暦が返すのと同じ補正済みの命式の上に描かれます。片方だけ送ると400 INVALID_LOCATIONを返します。送らない場合は万歳暦のデフォルト処理(現在は補正なし)が適用され、assumedLocationで示されます | |
country | string | 出生国、2文字のコード。座標なしでKR・JP・THを送ると、その国の代表経度で補正します(万歳暦と同じ) | |
birthTimePrecision | string | exact・approximate・estimated・unknown。補正はexactの場合のみ適用されます(位置を送った場合のデフォルトはexact)。exact以外の値では真太陽時の補正はありません。韓国の夏時間期間の出生は、万歳暦と同じく1時間引いて標準時として読みます(2026-10-16) | |
range | object | O | { "fromYear", "toYear" }、年運の範囲(新暦の年、最大101年)。出生年~出生年+100を一度取得し、画面で切り出して使うことをおすすめします |
monthsOfYear | integer | null | 月運の12スロットを計算する四柱推命上の年(その年の立春から翌年の立春の直前まで)。省略すると、現在(韓国時間)を含む四柱推命上の年 — 1月1日から立春の前までは前年です。nullにすると月運の層はありません(months: []) | |
lang | string | ko・en・ja・th。レスポンスの値は言語に依存しないコード(干支の韓国語読み、五行、関係名)なので、現在はどの言語でも結果は同じです。一覧は有効な値 > 言語に依存しないコード値を参照してください。 |
リクエスト例
{
"birthDate": "1990-05-15",
"birthTime": "14:30",
"calendar": "solar",
"gender": "male",
"timezone": "Asia/Seoul",
"range": { "fromYear": 1990, "toYear": 2090 },
"monthsOfYear": 2026
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/saju-flow \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: chart-123:flow:2026" \
-d '{"birthDate": "1990-05-15", "birthTime": "14:30", "calendar": "solar", "gender": "male", "timezone": "Asia/Seoul", "range": {"fromYear": 1990, "toYear": 2090}, "monthsOfYear": 2026}'
レスポンス例(抜粋、実際のエンジン出力)
{
"success": true,
"data": {
"engineVersion": "saju-flow-6",
"kbVersion": "2026.10.11-7",
"hourKnown": true,
"natalAmbiguous": null,
"natal": {
"score": -37, "result": "중화", "level": "약약",
"breakdown": { "season": -30, "support": 36, "control": -28, "hidden": -5, "root": 5 },
"primaryYongshin": "토",
"shin": { "yongshin": "토", "huishin": "화", "gishin": "목", "gushin": "수", "hanshin": "금" },
"ruleIds": ["R-SAJU-STR-001", "R-SAJU-STR-018", "R-SAJU-STR-019", "R-SAJU-YONG-170"]
},
"daeun": [
{ "startYear": 1997, "endYear": 2006, "startAge": 7,
"chars": [
{ "pos": "stem", "char": "임", "hanja": "壬", "ohaeng": "수", "sipsin": "식신", "shinRole": "gushin",
"share": { "support": 0, "control": -8, "hidden": 0, "root": 0, "total": -8 } },
{ "pos": "branch", "char": "오", "hanja": "午", "ohaeng": "화", "sipsin": "정관", "shinRole": "huishin",
"share": { "support": 0, "control": -10, "hidden": -5, "root": 0, "total": -15 } }
],
"delta": -23, "line": { "value": -60, "clamped": false },
"relations": [
{ "type": "자형", "from": "daeun", "with": "yearBranch", "a": "오", "b": "오", "ruleId": "R-SAJU-REL-044", "decisionRuleId": "R-SAJU-UN-036" },
{ "type": "육합", "from": "daeun", "with": "hourBranch", "a": "오", "b": "미", "ruleId": "R-SAJU-REL-015", "decisionRuleId": null }
],
"triples": [], "hapPulim": [ ... ] },
...
],
"years": [
{ "year": 2026, "daeunIndex": 2,
"chars": [ { "pos": "stem", "char": "병", "hanja": "丙", ... "share": { ..., "total": -10 } },
{ "pos": "branch", "char": "오", "hanja": "午", ... "share": { ..., "total": -15 } } ],
"delta": -25, "line": { "value": -33, "clamped": false },
"relations": [
{ "type": "천간합", "from": "seun", "with": "monthStem", "a": "병", "b": "신", "ruleId": "R-SAJU-REL-003", "decisionRuleId": null },
...
],
"withDaeun": [], "triples": [],
"hapPulim": [
{ "kind": "existing", "domain": "jiji", "pair": ["오", "미"], "status": "broken_by_dong",
"reasonCode": "branch_hap_broken", "params": { "incoming": "오", "origin": "seun" },
"triggeredBy": { "origin": "seun", "value": "오" },
"reasonFallback": "동기 오(seun) 도래 → 합반 깨짐" },
{ "kind": "new", "domain": "cheongan", "pair": ["병", "신"], "chartValue": "신", "incomingValue": "병", "incomingOrigin": "seun",
"reasonCode": "new_stem_hap", "params": { "incoming": "병", "origin": "seun", "partner": "신" },
"reasonFallback": "병(seun) + 원국 신 → 새 천간 합 형성" },
...
],
"ipchunNote": false },
...
],
"months": [
{ "index": 1, "startsAt": "2026-02-04T04:55:00+09:00",
"chars": [ { "pos": "stem", "char": "경", ... }, { "pos": "branch", "char": "인", ... } ],
"delta": 4,
"relations": [ { "type": "반합", "from": "wolun", "with": "yearBranch", "a": "인", "b": "오", "ruleId": "R-SAJU-REL-024", "decisionRuleId": "R-SAJU-UN-035" }, ... ] },
...
],
"compatInputs": {
"primaryYongshin": "토",
"surfaceElementCounts": { "목": 0, "화": 2, "토": 2, "금": 3, "수": 1 },
"surfaceAbsent": ["목"],
"hourKnown": true,
"ruleIds": ["R-SAJU-COMPAT-008", "R-SAJU-COMPAT-009", "R-SAJU-COMPAT-010"]
},
"caveats": ["R-SAJU-UN-028", "R-SAJU-PRAC-026", "R-SAJU-UN-034"],
"birthBeforeIpchun": false,
"assumedLocation": { "correction": "none" },
"costPoints": 0
}
}
フィールドの読み方
line:累積値 — 大運は命式+大運、年運は命式+その年の大運+年運。各段階で±100に切り詰め、切り詰めた場合はclamped: true(R-SAJU-UN-033)。月運には累積の線がなく、その月の分(delta)だけを返します。share:1文字分の内訳(生扶・剋洩・蔵干・通根)。層の重みは大運・年運・月運で1:1:1(R-SAJU-UN-030)、運の地支からの通根には上限がありません(R-SAJU-UN-031)。shinRole:その文字の五行の五神名(用神・喜神・忌神・仇神・閑神 — 有利・助ける・不利・害する・中立の五行。R-SAJU-YONG-170) — スコアではなく名前です。どの命式にも五神の表が付きます(nullになることはありません)。relations:運の文字と命式の文字の間の合・沖・刑の一覧(スコアには加算しません)。ruleIdは組み合わせ表のルール、decisionRuleIdはそれを運にも適用する根拠のルール(UN-035 月運、UN-036 自刑、UN-037 半合)です。withDaeunは年運↔その年の大運です。時柱が不明な場合、時柱との関係は出ません。triples:大運または年運の文字が、命式と合わせて3文字の三合や方合を完成させる場合(R-SAJU-UN-037)。hapPulim:大運・年運の文字が触れる命式の合(合が起こる・解ける・壊れる)と、新しくできる合(R-SAJU-HAP-021~027)。月運は含まれません。画面の文章はreasonCodeとparams(incoming入ってくる運の文字、origindaeun|seun、必要に応じてtarget・partner)から、アプリの言語で独自に組み立ててください。reasonFallbackはエンジンが書いた韓国語の文として常に入っており、アプリが知らないreasonCodeを受け取ったときに表示する代替用です。reasonCodeは現在7種類です。stem_hap_kept_jaenghap:命式の天干合はそのまま保たれ、同じ陽干の運の文字(incoming)は争合のため割り込めません。stem_hap_kept_tuhap:命式の天干合はそのまま保たれ、同じ陰干の運の文字(incoming)は妬合のため割り込めません。branch_hap_gi:運の文字(incoming)が命式の六合の一方の文字(target)と沖になり、合を起こします(合起)。branch_hap_released:運の文字(incoming)が命式の六合の一方の文字を刑し、合が解けます。branch_hap_broken:命式の六合の一方と同じ文字(incoming)が運で入ってきて、合が壊れます。new_stem_hap:運の天干(incoming)と、合を組んでいない命式の天干(partner)が新しく天干合を作ります。new_branch_yukhap:運の地支(incoming)と命式の地支(partner)が新しく六合を作ります。
startAge:大運数(最初の大運の年齢)。出生日(韓国の日付)の00:00から節入りまでの日数を、出生の時・分を入れずに数え、3日=1年で丸めます(R-SAJU-UN-038)。このルールはkbVersion2026.10.11-2から台帳にあります。ipchunNote:照会した時点(韓国時間)がその年の立春より前なら、今年のスロットだけtrue。1月1日から立春の前までは、まだ前年の年運が続いていることを示します。年運はその年の立春の干支を使います(R-SAJU-UN-016)。birthBeforeIpchun:1月1日から立春の前までに生まれ、命式の年柱が前年の干支になる場合はtrue(トップレベルのフィールド)。assumedLocation(saju-flow-5から、トップレベルのフィールド):位置が送られなかったときに計算に使ったデフォルト。現在は{ "correction": "none" }(真太陽時の補正なし)で、万歳暦と同じです。万歳暦のデフォルトが代表経度に変わると、{ "correction": "trueSolarTime", "longitude": … }が返ります。位置(birthLatitude・birthLongitudeまたはcountry)が送られた場合はnullです。natalAmbiguous:時刻が不明で、出生日に節入りがある場合は{ "pillar": "month" | "year", "termAt" }— エンジンは正午で判定するため、月柱(立春なら年柱も)が実際と異なる可能性があることを示します。compatInputs:複数人を重ねるときに、アプリが集合の共通部分を取るだけで済むようにする値(用神の五行、表に出ている文字の五行の数、表に出ていない五行)。人と人の間の合算や順位付けは出しません。
料金
- 販売がオフになっている場合は404
saju_flow_not_enabledを返します(課金なし)。 - 計算が成功した場合のみ差し引かれます。入力エラー(400 — 存在しない日付、101年を超える範囲など)と409は課金されません。レスポンスの
costPointsは差し引かれた金額(₩)で、利用ログのエンドポイントはsaju-flowです。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | saju_flow_not_enabled | アカウントでこの機能が有効になっていない |
| 400 | INVALID_DATE | birthDateの形式エラー、または存在しない日付 |
| 400 | INVALID_LUNAR_DATE | 存在しない旧暦の日付 |
| 400 | INVALID_RANGE | toYearがfromYearより前、または範囲が101年を超える |
| 400 | INVALID_TIME | birthTimeがHH:mm形式ではない |
| 400 | INVALID_LOCATION | birthLatitude・birthLongitudeの片方だけを送った |
| 409 | saju_flow_correction_unsupported | 位置は送られたが、補正後の命式と大運数を万歳暦と同じとおりに運勢フローへ引き継げない、まれな出生(実測で約0.1% — 例:補正で日付の境目をまたいで大運数が変わる、時刻不明の正午補正が節入りをまたぐ)。異なる値をでっち上げる代わりに拒否します(課金なし)。このような出生には、同じ位置で万歳暦APIを使ってください |
| 402 | (なし) | 残高が呼び出し価格より少ない — このAPIは呼び出し前の残高チェックがないため、コードなしの402が返ります |
相性API
2人の四柱推命から相性を計算します。1回の呼び出しで、四柱推命の相性(60×60の日柱相性表・目的別のスコアと6軸・天干/地支の関係・八字全体の五行バランス・通変星・相互の神殺(象徴的な星))、親密度の記号表(参考文献(1995)の男女日柱表による記号と等級)、星座の相性(太陽・月・アセンダントの3層に目的別の天体を加えたもの、星座相性の文章は最大2つ)、干支(生まれ年の動物)の相性(2人の生まれ年の動物の地支の関係と等級)を返し、さらに5つのスコアを目的別の重みで合わせた総合スコア(headerBreakdown)も返します。2026-10-16からは、2人の命式の間の合・沖・刑・害・破を位置ごとにまとめた関係表(relations)とそのスコア(p2Score)も返します。INTAアプリの相性画面と同じエンジンで、同じ入力なら常に同じ結果になります。
INTAアプリの代表スコア(大きな数字)=headerBreakdown.average(下のレスポンス例では62)。saju.score.total(例では59)は日柱表と八字だけを平均したHRUM独自のスコアなので、アプリ画面の数字とは異なります。
INTAアプリの結果画面の6軸グラフに表示される値はsaju.iljuAxesです(saju.axesは目的別に再計算した別の値です)。出生時刻がわかる人は、推奨の呼び出しのようにpersonXCountry+personXBirthTimePrecision: "exact"を送ると、INTAアプリと同じ方法(真太陽時の補正あり)で四柱推命が計算されます。
POST /api/v1/partners/v1/compat
2人の四柱推命をもとに相性を分析します。
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
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ブロックでは、relationRatingsのkey、meetingKeywords、authority、full8、conflict、さらに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(2時間単位の時辰まで)・estimated・unknown。星座の相性:時刻があればexact、なければunknownがデフォルトです。四柱推命:真太陽時の補正はexactのときだけ適用されます。省略して座標またはpersonXCountryを送るとexactとして扱います(万歳暦APIと同じルール) |
|
personABirthLatitude / personABirthLongitudepersonBBirthLatitude / personBBirthLongitude |
number | 出生地の座標(両方送ります)。アセンダントの計算と四柱推命の真太陽時補正の両方に使います(四柱推命への適用は2026-10-11から)。座標がない場合、アセンダントはpersonXCountryから、それもなければlangの国の代表座標から推定します(ko → 韓国、ja → 日本、th → タイ/enではアセンダントを省略) |
|
personABirthTimezoneOffset / personBBirthTimezoneOffset |
number | UTCとの差(分)、デフォルト540(KST)。座標と一緒に送ると、四柱推命の補正の標準子午線も決まります(省略時は経度に最も近いタイムゾーン)。personXBirthTimezoneも送った場合はそちらが優先されます |
|
personABirthTimezone / personBBirthTimezone |
string | 出生地のタイムゾーン(IANA、例:"America/New_York"、任意、2026-10-14)。万歳暦APIのtimezoneと同じルールで四柱推命を計算するため、同じ出生情報なら万歳暦APIと同じ四柱になります — ソウル以外では節気の入りの時刻をそのタイムゾーンで読み(夏時間を含む)、座標と一緒に送ると夏時間を除いた標準時差を補正の基準にします。personXBirthTimezoneOffsetより優先され、星座相性のチャートは、出生当時そのタイムゾーンで実際に使われていた時計の時刻(夏時間を含む)で作成します。省略すると従来どおり計算します(出生時刻を韓国時間として読みます)。名前を認識できない場合は省略したものとして計算し、レスポンスにwarnings(UNKNOWN_TIMEZONE、1人につき1件)が付きます |
|
personACalendar · personAIsLeapMonthpersonBCalendar · personBIsLeapMonth |
string · boolean | "lunar"にすると、生年月日を旧暦として受け取り、新暦に変換して計算します(デフォルト"solar")。IsLeapMonth: trueは閏月です。その年にその閏月がない場合や旧暦の日付が存在しない場合は400 INVALID_LUNAR_DATE(課金なし)。どちらか一方でも旧暦で送ると、レスポンスにlunarInput({a, b}、万歳暦APIと同じ形式)が付きます |
|
personACountry / personBCountry |
string | 出生国の2文字の国コード。座標なしでKR・JP・THを送ると、その国の代表経度で四柱推命の時刻を補正します(その他の国は補正なし)。星座の相性でもlangの代わりにこの国でアセンダントを推定します |
|
personAZaSiRule / personBZaSiRule |
string | 子の刻(23時以降)の日柱:"traditional"(デフォルト、翌日の日柱)・"yajaSi"(夜子時、当日の日柱・出生地補正後、23時台の時柱の天干は翌日の日干を基準にします、2026-10-20から) |
|
details |
boolean | デフォルトはfalse。trueにすると、saju.full8(八字の詳細分析)・saju.conflict({pattern, tip}、衝突のパターンとアドバイス)・saju.relationScores(天干/地支の関係スコア)・トップレベルのdictionary({a, b}、2人の日柱辞典 — 干支の組の基本値(五行・陰陽・蔵干・十二運星)、性格キーワード、一行の要約)が追加されます。dictionary.a/bのid(ilju_경진)とname_krは、言語に依存しない日柱のコード値(韓国語)です。enとthでは天干・地支の1文字や十二運星などをローマ字(Gap・Mogyok)で、jaでは漢字で表記します。saju.full8の中のpersonA/B.elementDistribution・sipsinCount・combinedElementBalance.distributionのオブジェクトキーは、言語に依存しない韓国語のコード値(목、비견など)です。一覧は有効な値 > 言語に依存しないコード値を参照してください。 |
|
flow |
boolean | デフォルトはfalse。trueにすると、yearFlow(2人の5年間の流れ、基準年±2)とdayFlow(2人の15日間の流れ、基準日±7)が追加されます |
|
date |
string | flowの基準日、YYYY-MM-DD(1900-2100)。デフォルト:韓国時間の今日 |
|
currentYear |
number | yearFlowの基準年(1900–2100)。デフォルト:dateの年 |
|
personAMbti / personBMbti |
string | 4文字のMBTI(例:ENFP、大文字・小文字を区別しません)。2人とも送ると、トップレベルにmbti(MBTI相性、韓国語)が追加されます |
details・flow・MBTIのオプションは追加料金なしです(1回あたり₩20のまま)。
- 時刻の補正:各人の四柱推命(日柱・八字スコア・総合スコア・親密度の記号表・干支・権威の分析・
yearFlow・関係の文章)は1回だけ計算し、すべての項目で共有します。座標、personXCountry、精度exactのいずれも送らない場合は、入力した時刻をそのまま使います(万歳暦APIと同じ)。INTAアプリ(韓国、時刻を直接入力)と同じ相性が必要な場合は、2人ともpersonXCountry: "KR"(+personXBirthTimePrecision: "exact")を送ってください — 下の推奨の呼び出しを参照してください。出生時刻のない人は補正しません。デフォルト(送らなければ補正なし)は変わりません。 - 2026-10-11の変更:座標を送ると、四柱推命にも真太陽時の補正がかかるようになりました(以前は星座の相性にだけ使っていました)。この変更で1つのレスポンス内で四柱推命と星座が同じ時刻基準を使うようになったため、すでに座標を送っていた呼び出しでは四柱推命のスコアや日柱が変わることがあります。新しいフィールドと座標なしの呼び出しのレスポンスは変わりません。
- 日柱はコード値です:
saju.personA.iljuとsaju.personB.iljuの値(例:계미)は、langにかかわらず韓国語の干支コード値です。表示名には、万歳暦APIの用語集(glossary)または漢字表記(癸未、英語とタイ語では癸未 (Gye-mi))に変換してください。
推奨の呼び出し(INTAアプリと同じ結果)
出生時刻がわかる人は、出生国と"exact"を一緒に送ってください。真太陽時の補正がINTAアプリと一致するため、時辰の境目の近くで生まれた人でも、アプリと同じ日柱とスコアになります。
{
"personABirthDate": "1990-09-04", "personABirthTime": "14:30", "personAGender": "male",
"personACountry": "KR", "personABirthTimePrecision": "exact",
"personBBirthDate": "1992-02-20", "personBBirthTime": "10:15", "personBGender": "female",
"personBCountry": "KR", "personBBirthTimePrecision": "exact",
"purpose": "yeonae_attraction", "details": true
}
レスポンス例
以下は実際のエンジン出力です(A 男性 1990-09-04 14:30、B 女性 1992-02-20 10:15、恋愛、座標なし)。2026-10-10に追加された常に含まれるフィールド(saju.relationRatings・saju.meetingKeywords・saju.authority・tti.conflictFrame)はこの例から省いています — 下のオプションの例を参照してください。この2人の場合、推奨の呼び出し(KR+exact)でも値は同じです。
{
"success": true,
"data": {
"personABirthDate": "1990-09-04", "personABirthTime": "14:30", "personAGender": "male",
"personBBirthDate": "1992-02-20", "personBBirthTime": "10:15", "personBGender": "female",
"tti": {
"userTti": "말", "partnerTti": "원숭이",
"relation": { "type": null, "detail": null, "relations": [] },
"tier": "흉"
},
"saju": {
"purpose": "yeonae_attraction",
"hourKnown": { "a": true, "b": true },
"personA": { "ilju": "임신" },
"personB": { "ilju": "병인" },
"score": { "total": 59, "grade": "맞춰 가면 좋아요",
"breakdown": { "ilju": 53, "authority": 65, "eightChar": 65 } },
"axes": { "attraction": 25, "stability": 59, "growth": 58,
"communication": 24, "passion": 74, "longevity": 65 },
"pattern": { "name": "폭발형",
"description": "에너지가 크게 부딪히는 뜨거운 관계예요. 감정이 커질 때 잠시 쉬어 가는 규칙이 도움이 돼요." },
"relation": { "summary": "천간충 + 인신충",
"stem": { "type": "천간충", "detail": "병임충" },
"branches": [ { "type": "지지충", "detail": "인신충" } ] },
"elements": { "basis": "eight", "aLacks": [], "bProvidesToA": [], "bLacks": ["토"], "aProvidesToB": ["토"] },
"tenGods": { "aView": "편재", "bView": "편관(칠살)" },
"bestFor": ["단기 끌림"],
"weakFor": ["결혼·동거"],
"highlights": [ "상대의 시지에 나의 천을귀인 (사) 발현 — 상대가 나의 해결사" ],
"iljuAxes": { "attraction": 45, "stability": 16, "growth": 88,
"communication": 60, "passion": 70, "longevity": 50 }
},
"categoryNarrative": {
"category": "romantic", "purpose": "yeonae_attraction", "lang": "ko",
"text": "상대 쪽의 즉각적인 열정과 나 쪽의 자유로운 흐름은 불과 물처럼 정면으로 맞부딪혀서, 처음 만났을 때의 팽팽한 긴장감이 곧 끌림이 되기 쉬워요. 짧고 뜨거운 설렘이 큰 관계라, 감정이 치솟는 날엔 하루쯤 식힐 틈을 두면 더 즐겁게 만날 수 있어요.",
"styleVersion": "v2"
},
"costPoints": 20,
"classic1995": {
"symbol": "××", "grade": "대흉", "score": 50,
"ttiRelation": { "type": null, "detail": null, "relations": [] },
"conflictFrame": false
},
"relations": [
{ "positions": ["month", "month"], "kind": "chung", "tier": "heavyClash",
"ruleIds": ["R-SAJU-REL-034", "R-SAJU-COMPAT-106", "R-SAJU-COMPAT-112"], "chars": ["申", "寅"] },
{ "positions": ["day", "day"], "kind": "chung", "tier": "heavyClash",
"ruleIds": ["R-SAJU-REL-034", "R-SAJU-COMPAT-106", "R-SAJU-COMPAT-112"], "chars": ["申", "寅"] },
{ "positions": ["day", "day"], "kind": "stemChung", "tier": "clash",
"ruleIds": ["R-SAJU-REL-008", "R-SAJU-COMPAT-110"], "chars": ["壬", "丙"] },
{ "positions": ["year", "year"], "kind": "napeumSaeng", "tier": "gather",
"ruleIds": ["R-SAJU-BASE-037", "R-SAJU-COMPAT-111"], "chars": ["庚午", "壬申"] },
{ "positions": ["chart", "chart"], "kind": "banghap", "tier": "gather",
"ruleIds": ["R-SAJU-REL-021", "R-SAJU-COMPAT-104"], "chars": ["巳", "午", "未"] }
],
"p2Score": 57,
"astroSynastry": {
"self": {
"sun": { "signEn": "Virgo", "element": "earth", "modality": "mutable" },
"moon": { "signEn": "Pisces", "element": "water", "modality": "mutable", "uncertain": false },
"ascendant": { "signEn": "Sagittarius", "element": "fire", "modality": "mutable", "uncertain": false, "countryBasis": true },
"venus": { "signEn": "Leo", ... }, "mars": { "signEn": "Gemini", ... },
"mercury": { ... }, "jupiter": { ... }, "saturn": { ... }
},
"partner": { "sun": { "signEn": "Pisces", ... }, "moon": { "signEn": "Virgo", ... }, ... },
"layers": [
{ "key": "sun", "relation": "opposite", "selfSign": "Virgo", "partnerSign": "Pisces",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "key": "moon", "relation": "opposite", "selfSign": "Pisces", "partnerSign": "Virgo",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "key": "ascendant", "relation": "neutral", "selfSign": "Sagittarius", "partnerSign": "Taurus",
"textKey": "compat.astro.relation.neutral",
"text": "뚜렷한 결 없이 각자의 스타일을 존중하면 되는 조합이에요" }
],
"purposeBodies": [
{ "body": "venus", "relation": "opposite", "selfSign": "Leo", "partnerSign": "Aquarius",
"textKey": "compat.astro.relation.opposite",
"text": "충 — 정반대라 방향은 다르지만 서로를 끌어당길 수 있어요" },
{ "body": "mars", "relation": "same_element", "selfSign": "Gemini", "partnerSign": "Aquarius",
"textKey": "compat.astro.relation.same_element",
"text": "같은 원소 — 서로의 방식을 바로 알아볼 만큼 편안할 수 있어요" }
],
"caveats": ["compat.astro.caveat.ascendantCountryBasis"],
"caveatTexts": ["상승궁은 출생 도시가 없어 국가 대표 좌표로 추정했어요"],
"score": 64
},
"astroReadings": [
{ "key": "Su_Mo_ss", "lang": "ko",
"text": "한쪽의 태양과 다른 쪽의 달이 같은 별자리에 놓이면, 한 사람이 향하는 방향을 다른 사람의 마음이 낯설지 않게 알아보는 깊은 공명이 생기기 쉬워요. 닮은 만큼 같은 그림자도 함께 커질 수 있으니 서로의 빈틈을 웃으며 짚어 주면 좋아요." },
{ "key": "Ve_Ma_op", "lang": "ko",
"text": "한쪽의 금성과 다른 쪽의 화성이 정반대 별자리에 놓이면, 서로에게 없는 매력을 알아보며 끌리는 보완의 흐름이 생기기 쉬워요. 원하는 속도와 표현 방식이 반대로 기울 수 있으니 서로의 선을 말로 정해 두면 그 끌림이 편안하게 이어져요." }
],
"headerBreakdown": {
"sixAxis": 55, "authority": 65, "full8": 65, "classic": 57, "natal": 64,
"average": 62, "purpose": "yeonae_attraction",
"weights": { "sixAxis": 0.2, "authority": 0.3, "full8": 0.2, "classic": 0.1, "natal": 0.2 }
},
"engineVersion": "compat-2",
"lang": "ko"
}
}
saju(四柱推命の相性)がメインです。まれに日柱を計算できない場合はnullになります — その場合はttiだけを表示してくださいsaju.score.total:0–100。日柱表のスコアと八字分析のスコア(それぞれbreakdown内)の平均です。gradeはわかりやすい言葉の等級です — 아주 잘 맞아요(とても相性が良い、85以上)・잘 맞아요(相性が良い、75以上)・무난해요(無難、65以上)・맞춰 가면 좋아요(歩み寄ればうまくいく、55以上)・서로 많이 달라요(互いにかなり違う)。この値は以前と同じです — 記号表と星座も含めたスコアはheaderBreakdown.averageですsaju.axes:6軸(0–100)— 惹かれ合い・安定・成長・コミュニケーション・情熱・持続性。purposeによって変わります。saju.pattern:関係タイプの名前と説明(なければnull)saju.iljuAxes(2026-10-27から):INTAアプリの結果画面の6軸グラフと同じ値です — 2人の日柱の組の相性表にある6軸をそのまま返します(attraction・stability・growth・communication・passion・longevity、0–100、purposeに依存しません)。6軸の平均がheaderBreakdown.sixAxisです。saju.axesと同じキーですが、計算方法が異なるため数値は違います。組が相性表にない場合はnullsaju.elements:各人の命式全体の五行分布から計算します(時刻が不明なら6文字 —basis: "six")。bProvidesToA=Aに足りずBが持っている五行saju.tenGods:Aから見たBの通変星(aView)とその逆(bView)。highlights:八字の中に見つかった相互の神殺の文章(最大5件、なければ空配列)relations(2026-10-16から):2人の命式の間の関係の一覧です。同じ位置(年・月・日・時 — 時柱は2人とも出生時刻がある場合のみ)の地支の組、2人の日干の間の干合と干沖、年柱の納音五行、そして2つの命式を合わせたときにだけ成立する三合と方合を調べます。各項目にはpositions([A side, B side]—year・month・day・hour、三合・方合ではchart=命式全体)、kind(下の表)、tier、ruleIds(根拠となるKBルールのID — 原典はKB APIで確認できます)、chars(関係する文字、漢字)があります。キーはすべて言語に依存しないため、langを変えても同じです。表示用のテキストはkindから自分で作ってください。吉凶を判定する言葉はありません。命式を作れない場合はnull、関係がなければ空配列tier:gather集まる(合の側)・clash摩擦・heavyClash強い摩擦(古典でより重いとされる関係。現在は沖)・listOnly列挙のみ(古典に方向が見つからなかったため、スコアに入れない関係)p2Score(2026-10-16から):0–100。round(71.6 + 5 × Σ)を0–100に収めた値です — Σ=関係ごとにgather+1・clash−1・heavyClash−2・listOnly0を合計したもの。1単位=5点で、71.6は関係がないときの中立点です(以前の古典軸スコアの実会員平均、2026-10-16時点)。時柱の有無にかかわらず同じ尺度です。古典が述べているのは関係の方向と順位だけで、大きさではありません — この数値は表示のための尺度の仮定であり、古典から得たスコアではありません(KBR-SAJU-COMPAT-113)。relationsがnullならnullclassic1995(提供終了予定):今も以前とまったく同じように返します。予定:2026-11-16に告知 → 2026-12-31まで維持 → 2027-01-01からnull。日程はサービスのお知らせで変わることがあります。新規の連携ではrelationsとp2Scoreを使ってください。参考文献(1995)の男女日柱の親密度表による記号です(●대길(大吉)100・◎중길(中吉)90・○길(吉)80・△무해무덕(可もなく不可もなし)70・×흉(凶)60・××대흉(大凶)50)。この表は男性の日柱×女性の日柱という向きがあるため、同性の組や性別を送らない場合は両方向(Aを男性・Bを男性)を読み、scoreは2つの平均(例:95)、symbolとgradeはその平均を10の位で切り捨てた等級になります(例:95 →◎중길)。両方向が同じなら、その記号をそのまま返します。conflictFrame:記号は良いのに干支の関係が悪い場合、またはその逆の場合にtrue。日柱が見つからない場合はオブジェクト全体がnullastroSynastry:星座の相性。layers=太陽・月・アセンダントの3層の比較、purposeBodies=目的別の優先天体(恋愛:金星・火星、結婚:+土星、友人:水星・木星…)。relation=same_sign・opposite・same_element・element_support・same_modality・element_friction・neutral。textはその意味です(lang)。score0–100。caveats/caveatTexts:アセンダントや月のサインを推定したときの注記。時刻が不明な場合、アセンダントの層は省かれますastroReadings:2人のチャートの間で特に目立つ接点(太陽–月、金星–火星など)について、最大2つの作成済みリーディング文章。なければ空配列。各文章のlangは、テキストが実際に書かれている言語です(リクエストした言語のテキストがなければko)headerBreakdown:5つのスコア — 6軸の平均・権威(authority)・八字(full8)・古典の比重(classic— 2026-10-16からはp2Score、それ以前はclassic1995.score)・星座(natal)— をpurposeごとの重み(weights)で合わせた総合スコアaverage(0–100)。欠けているスコアの重みは残りに配分し直します。INTAアプリの相性画面の代表スコア(大きな数字)と同じ値です(上の例では62)。2026-10-16から、結婚の目的(marriage_stability)での古典の比重(classic)の重みを0.25から0.05にし、空いた0.20を他の4軸に従来の比率で配分しました(sixAxis0.15 → 0.19・authority0.25 → 0.3167・full80.25 → 0.3167・natal0.10 → 0.1267)。他の目的の重みは変わりません。日柱の相性表の項目が見つからない場合はnull- 生まれ年は1900–2100である必要があります — それ以外は400
INVALID_BIRTH_YEAR(課金なし)。ユーザーが日付欄に2桁の年を入力すると例えば0090として入るため、画面側でも防いでください。相性表に結果が見つからない場合は400COMPAT_UNAVAILABLE(課金なし) tti.tier:参考文献(1995)の干支の相性による等級の文字列(例:대길・길・중길・보통・주의・흉 — 大吉から凶まで)。tti.relation.type=2つの動物の地支の関係 —충(沖)・원진(怨嗔)・형(刑)・해(害)・육합(六合)・반합(半合)・파(破)のいずれか(複数重なる場合はこの順で最初のもの)、なければnull。detailは半合のときだけ(例:수국(水局))。tti.relation.relations=重なっているすべての関係(同じ順、例:丑・未["충","형"]、なければ空配列)ttiには動物・関係・等級だけが入ります。参考文献の干支相性の文章は含まれません(2026-10-11から)。categoryNarrative:この関係(purpose)での2人の様子を2–3文で表したもの。文章はすべての日柱の組み合わせ(1,830組)と6つの関係の種類ごとに作成済みなので、同じ入力なら常に同じテキストになります。文中の나=A、상대=Bです(英語はYou/Your partner、日本語はあなた/相手、タイ語はคุณ/คู่ของคุณ)。langで4言語。テキストが見つからなければnull(課金は同じ)- 常に含まれる(2026-10-10から):
saju.relationRatings=5つの関係の種類ごとの{ key, stars }(keyの例:연애(恋愛)、결혼·동거(結婚・同居)、친구(友人)、사업 파트너(ビジネスパートナー)、장기 관계(長期的な関係)/星1–5)・saju.meetingKeywords=出会いのキーワード3つ・saju.authority=権威の相性の判定(finalScore・grade・gradeTier・pattern・summary・levels(L1–L4)・factors・flags・climateBalance)・tti.conflictFrame=classic1995.conflictFrameと同じ値 yearFlow.years[].tier:great・good・neutral・caution。dayFlow.days[].tier:golden・good・neutral・dim・hard(dayFlow.golden/hardはその日付の一覧)
関係の種類(relations[].kind)
kind | 意味 | tier |
|---|---|---|
yukhap | 地支の六合 — 2つの地支が組になって合わさる | gather |
banhap | 地支の半合 — 三合の3文字のうち2文字 | listOnly |
samhap | 三合 — 2つの命式を合わせると3文字がそろい、1つの五行の局を作る | gather |
banghap | 方合 — 2つの命式を合わせると同じ季節の地支3つがそろう | gather |
chung | 地支の沖 — 正面からぶつかる | heavyClash |
hyung | 地支の刑 | clash |
hae | 地支の害 | clash |
pa | 地支の破(寅亥・巳申の組は六合なのでlistOnly) | clash |
wonjin | 怨嗔(恨み) | listOnly |
stemHap | 2人の日干の間の干合 | gather |
stemChung | 2人の日干の間の干沖 | clash |
napeumSaeng | 年柱の納音五行が互いに生じる | gather |
napeumBihwa | 年柱の納音五行が同じ | gather |
napeumGeuk | 年柱の納音五行が互いに剋する | clash |
同じkindは常に同じtierです(例外は破の2組だけです)。新しい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 }, ... }
}
}
注意事項
- 基本データ:2人の生年月日は必須です。時刻と性別は任意です。親密度の記号表は、性別がなくても同性でも返します(両方向を合わせたもの)。星座の相性のアセンダントには出生時刻が必要です。
- 得られるもの:星座の相性はトロピカル方式の黄道十二宮を使います。関係の文章は
categoryNarrative、星座の文章はastroReadingsで返ります。より長い独自のリーディングが必要な場合は、結果を/readingの質問に入れてください。 - 2026-10-16の変更(
engineVersioncompat-2):relations・p2Score・engineVersionが新しく加わり、headerBreakdown.classicがp2Scoreになったため、headerBreakdown.averageが以前と変わることがあります(INTAアプリの相性画面と同じ値)。その他の既存フィールドの値は変わりません。 - 互換性:2026-10に追加されたフィールド(
classic1995・astroSynastry・astroReadings・headerBreakdown・lang、2026-10-10のsaju.relationRatings・saju.meetingKeywords・saju.authority・tti.conflictFrame)は、langを送るかどうかにかかわらず常に追加されます。既存フィールドの値は変わりません。ただし2026-10-11から、参考文献(1995)の文章を再現していたフィールド — 干支相性の一行リーディングと、日柱辞典の恋愛運・健康運 — はレスポンスから削除されています。 - 2026-10-27の追加:
saju.iljuAxes(常に、sajuブロックの最後)が新しく加わりました。既存フィールドの値と順序は変わらず、engineVersionもcompat-2のままです。 - 2026-10-31の変更:相性の文章の韓国語の助詞が、直前のパッチム(終声)に合うようになりました(例:「임와」 → 「임과」、「병는」 → 「병은」)。キー、順序、数値、他の言語のテキストは変わりません。
- 料金:1回の呼び出しごとに₩20が差し引かれます(追加されたフィールドと
details・flow・MBTIのオプションを含み、追加料金はありません)。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | INVALID_BIRTH_YEAR | どちらかの生まれ年が1900–2100の範囲外 |
| 400 | INVALID_LUNAR_DATE | 旧暦の日付が存在しない |
| 400 | COMPAT_UNAVAILABLE | この日柱の組み合わせの相性データがない |
| 402 | INSUFFICIENT_BALANCE | 残高不足 |
リクエスト例は、上のオプションの例と実行例を参照してください。
性格タイプAPI
MBTIベースの性格診断を提供します。無料のライト版(24問)とプレミアム版(93問)に対応しています。
GET /api/v1/partners/v1/personality-type/questions
性格診断の質問を取得します。無料です。
curl "https://api.hrum.ai/api/v1/partners/v1/personality-type/questions?tier=free" \
-H "X-Partner-Api-Key: your-api-key"
リクエストパラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
tier |
string | 診断のバージョン("free"または"premium"、デフォルト:"free") |
レスポンス例
{
"success": true,
"data": {
"tier": "free",
"count": 24,
"questions": [
{
"id": "q_001",
"text": "갑자기 생긴 모임에도 일단 가본다",
"choices": [
{ "value": 1, "label": "전혀 그렇지 않다" },
{ "value": 2, "label": "그렇지 않다" },
{ "value": 3, "label": "보통이다" },
{ "value": 4, "label": "그렇다" },
{ "value": 5, "label": "매우 그렇다" }
]
}
]
}
}
POST /api/v1/partners/v1/personality-type
性格診断の回答を送信し、性格タイプを分析します。
curl -X POST https://api.hrum.ai/api/v1/partners/v1/personality-type \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"tier": "free",
"answers": [
{ "questionId": "q_001", "answer": 4 },
{ "questionId": "q_002", "answer": 2 }
]
}'
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
answers |
array | O | 回答の配列 [{ "questionId": "q_001", "answer": 4 }, ...]。questionIdは質問のレスポンスのid(形式q_001)、answerは1–5の整数です。premiumでは4つの軸(外向/内向・感覚/直観・思考/感情・判断/知覚)それぞれに少なくとも1つの回答が必要です(ない場合は400 personality_axis_unanswered)。正確な結果のため、質問のエンドポイントで受け取った93問すべてに回答することをおすすめします |
tier |
string | O | "free"または"premium" |
レスポンス例
{
"success": true,
"data": {
"personalityType": "ENTJ",
"typeLabel": "지휘관",
"scores": {
"extraversion": 72,
"sensing": 45,
"thinking": 68,
"judging": 80
},
"tier": "premium",
"costPoints": 10
}
}
料金
- 無料版(free):24問、₩0(無料)
- プレミアム(premium):93問、₩10/回
- 不明な
questionIdや1–5の範囲外のanswerは400を返し、課金されません。 premiumで回答がまったくない軸がある場合、400personality_axis_unansweredになり、課金されません。レスポンスのaxesに空の軸(E_I・S_N・T_F・J_P)が入ります。
エラーコード
共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:
| HTTP | コード | 発生条件 |
|---|---|---|
| 400 | (なし) | 質問の取得 — tierがfreeでもpremiumでもない/回答の送信 — 不明なquestionId |
| 400 | personality_axis_unanswered | 回答の送信 — premiumで、回答がまったくない軸がある(空の軸はaxesに入ります) |
| 402 | INSUFFICIENT_BALANCE | 回答の送信 — premiumで、残高不足 |
1–5の範囲外の回答は共通の400を返します。いずれも課金されません。
解釈KB API
このAPIは、利用を申請したアカウントにだけ公開されています。それ以外のアカウントには3つのパスすべてで404 kb_saju_explain_not_enabledを返します(課金なし)。利用するにはサポートにお問い合わせください。
四柱推命の命式で成立する関係(合・沖など)と構造(通変星・蔵干など)を、ルールカードと説明文で解説します。LLMを使わないため、同じ入力なら常に同じ結果になります。
POST /api/v1/partners/v1/kb/saju/explain
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
birth | object | O | 万歳暦APIのリクエスト本文と同じフィールド(year・month・day・hour?・minute?・timezone・gender・calendar? …)。birth.langは無視されます。birth.timezoneを認識できない場合、レスポンスにwarnings(field: "birth.timezone")が付きます |
sections | string[] | relations・structure・all。省略するとすべて(relations → structureの順) | |
level | string | L1(デフォルト)・L3。L3の説明がない項目はL1で埋め、fallbackLevelが付きます | |
lang | string | koのみ対応しています | |
channel | string | stable(デフォルト、レビュー済みの説明のみ)・preview(まだレビューしていない説明も含む — 特別に許可されたアカウントのみ。それ以外は403 KB_PREVIEW_NOT_ALLOWED) |
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/kb/saju/explain \
-H "X-Partner-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"birth": {
"year": 1990, "month": 5, "day": 17, "hour": 14, "minute": 30,
"timezone": "Asia/Seoul", "gender": "female"
},
"sections": ["relations"]
}'
レスポンス例(抜粋)
{
"success": true,
"data": {
"kbVersion": "2026.10.09-3",
"kbHash": "sha256:24b9a2d9...",
"channel": "stable",
"chart": {
"pillars": {
"year": { "stem": "庚", "branch": "午" },
"month": { "stem": "辛", "branch": "巳" },
"day": { "stem": "壬", "branch": "午" },
"hour": { "stem": "丁", "branch": "未" }
},
"timeUnknown": false
},
"sections": [
{
"id": "relations",
"title": "...",
"steps": [
{
"fact": { "type": "stem_pair", "a": "壬", "b": "丁", "posA": "day", "posB": "hour", "relation": "hap" },
"factText": "일간 壬과 시간 丁은 천간합(天干合) 관계다.",
"componentId": "saju:stem_pair:丁壬:hap",
"rules": [
{ "id": "R-SAJU-REL-004", "kind": "definition", "status": "verified", "sourceCount": 2,
"statement": "丁과 壬은 천간합 관계이고, 이 짝의 합화 오행은 목(木)이다." }
],
"interp": {
"meaning": { "text": "丁(정)과 壬(임)은 천간합으로 묶이는 짝이고, ...", "reviewed": false },
"why": { ... },
"pitfall": { ... }
}
}
],
"absent": [
{ "type": "stem_pair", "a": "庚", "b": "辛", "posA": "year", "posB": "month",
"note": "庚과 辛은 천간합·천간충 어느 것도 아니다." }
]
}
],
"unregistered": [],
"pendingReview": []
}
}
interpには説明のフィールド(meaning意味・why根拠・pitfall注意点)が入ります。各フィールドは{text, reviewed, reviewedBy?, notes?}で、stableではレビュー済みのフィールドだけを返します。unregistered:成立しているがまだ説明がない項目。pendingReview:説明はあるが、まだレビューされていないためstableでは表示されない項目。- ルールカードの原典は、下の
GET /kb/rules/{id}で確認できます。
GET /api/v1/partners/v1/kb/rules/{id}
ルールカード1枚とその原典を返します。無料です。
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
現在公開されている解釈KBの版を返します。無料です。domainを省略するとsajuです(例:saju・ziwei・astro・dream・tarot)。
curl "https://api.hrum.ai/api/v1/partners/v1/kb/release?domain=saju" \
-H "X-Partner-Api-Key: your-api-key"
{
"success": true,
"data": {
"version": "2026.10.09-3",
"hash": "sha256:24b9a2d9...",
"publishedAt": "2026-10-09T00:00:00.000Z",
"channel": "stable",
"counts": { "rules": 412, "interps": 1236 }
}
}
上の数値は例です。結果を保存する場合は、hashが変わったときに取得し直してください。
エラーコード
共通エラーに加えて:
| HTTP | コード | 発生条件 |
|---|---|---|
| 404 | kb_saju_explain_not_enabled | アカウントが申請していない(3つのパスすべて) |
| 400 | INVALID_LUNAR_DATE・INVALID_LOCATION | explain — 旧暦の日付が存在しない/緯度と経度の片方だけを送った |
| 403 | KB_PREVIEW_NOT_ALLOWED | explain — channel: "preview"を使えないアカウント(課金なし) |
| 400 | KB_DOMAIN_UNKNOWN | release — 対応していないdomain |
| 404 | KB_RULE_NOT_FOUND | rules — 不明なルールID |
| 503 | KB_NOT_LOADED | 解釈KBの版がまだ読み込まれていない。しばらくしてから再試行してください |
explainは成功した呼び出しだけを課金し、失敗した呼び出しは₩0として記録されます。
アプリメールAPI
RIDM Appsでホストしているアプリが、新規登録の確認、注文のお知らせ、パスワードの再設定などのトランザクションメール・サービスメールを送るためのAPIです。アプリキー(HRUM_API_KEY、コンソール > マイアプリ > AI連携)でのみ呼び出せます。通常のAPIキーで呼び出すと403 MAIL_APP_KEY_REQUIREDを返します。アプリのコンテナではSMTPポートがブロックされているため、メールはこのAPIで送ってください。
- 送信元アドレスはRIDM Appsのメール送信用アドレスで、送信者名はアプリ名(コンソール > マイアプリ > メールで変更できます)の後ろに「(RIDM Apps)」が付きます(例:
Moonlight Bakery (RIDM Apps))。銀行、カード・決済ブランド、公的機関(税務署、警察、検察、政府、郵便局など)の名前や、HRUM・RIDMのような名前は送信者名に使えません。返信はreplyToまたはコンソールで設定したアドレスに届きます。 - メール認証済みのコンソールアカウントを持つパートナーだけが送信できます。認証前はAPIが403
MAIL_EMAIL_UNVERIFIEDを返します。 - 広告メールは送れません。件名が
(광고)(「(広告)」)で始まるものは400で拒否されます。割引やイベントのお知らせなどの商業広告は、韓国の情報通信網法第50条により受信者の事前同意と受信拒否の手段が必要なため、このAPIでは送らないでください(利用規約第20条の2)。 - 受信者1人を1通と数えます。1回のリクエストに最大10人の受信者を入れられます。それぞれ個別に送るため、受信者どうしは互いのアドレスを見られません。
- バウンスした(存在しない)アドレスやスパム報告をしたアドレスには、その後送信せず
suppressedと返します。これらはカウントされず、課金もされません。 - メールの種類(
kind):デフォルトはtransactional(新規登録・注文・パスワードなど、必ず送る必要があるお知らせ)で、これまでどおり送信されます。受信者がオフにできるアプリの通知(新しいコメント、予約のリマインダーなど)は"kind": "notification"で送ってください。このメールにはワンクリック配信停止のヘッダー(List-Unsubscribe、List-Unsubscribe-Post、RFC 8058)が付くため、Gmailなどのメールアプリに「配信停止」ボタンが表示されることがあります。配信停止したアドレスには、そのアプリのnotificationメールだけを送らず、suppressedと返します(カウントなし、課金なし)。同じアドレスへのtransactionalメールや他のアプリからのメールは引き続き届きます。notificationも広告メールではありません — 広告はどの種類でも送れません。配信停止の記録は3年(1,095日)保存され、その後削除されると、そのアドレスに再びnotificationメールが届くことがあります。 - 自動停止:直近30日間で、スパム報告が送信数の0.1%(最低2件)、または恒久的なバウンスが5%(最低10件)に達すると(送信数が200未満の場合は200として計算)、そのアプリのメール送信を直ちに停止し、お知らせします。なりすましやフィッシングが疑われる場合も同様です。アプリ自体は動き続けます。停止中はAPIが403
MAIL_SUSPENDEDを返します。解除するにはcontact@float.doにお問い合わせください(利用規約第20条の2)。
POST /api/v1/partners/v1/mail/send
リクエストパラメータ
| パラメータ | 型 | 必須 | 説明 |
|---|---|---|---|
to | string | string[] | O | 受信者のアドレス1–10件。表示名付きのアドレス(Name <address>)は受け付けません |
subject | string | O | 件名、1–200文字、改行不可 |
text | string | △ | 本文(プレーンテキスト)。textとhtmlのどちらかが必須です。最大100,000文字 |
html | string | △ | 本文(HTML)、最大200,000文字。送信前に整理されます:script・style・iframe・フォーム・イベント属性は削除され、リンクはhttp(s)・mailto・telのみ、画像はhttpsのみ残ります。textがない場合は、HTMLからプレーンテキストの本文を作って一緒に送ります |
replyTo | string | 返信先アドレス。ない場合はコンソールで設定したアドレス、それもなければ返信先なしで送信します | |
attachments | object[] | 添付ファイル最大3件、合計512KB。{ "filename", "contentType", "content" }(contentはbase64)。PDF・PNG・JPEG・GIF・WebP・TXT・CSV・ICSのみ受け付けます | |
kind | string | transactional(デフォルト)・notification。notificationでは、ワンクリック配信停止のヘッダーが付き、そのアプリの配信を停止したアドレスには送りません(suppressed) |
リクエスト例
curl -X POST https://api.hrum.ai/api/v1/partners/v1/mail/send \
-H "Content-Type: application/json" \
-H "X-Partner-Api-Key: $HRUM_API_KEY" \
-d '{
"to": "user@example.com",
"subject": "Welcome aboard",
"text": "Your sign-up is complete. Get started with the link below.",
"html": "<p>Your sign-up is complete.</p><p><a href=\"https://myapp.ridm.ai\">Get started</a></p>"
}'
レスポンス例
{
"success": true,
"data": {
"requestId": "7f1c2a3e-…",
"results": [ { "to": "user@example.com", "status": "sent", "messageId": "<…>" } ],
"sent": 1,
"chargedWon": 0
}
}
statusはsent(メールサーバーが受け付けた)・failed(送信できなかった — 課金なし)・suppressed(アドレスがバウンスまたはスパム報告をしたため、もしくはそのアプリのnotificationメールの配信を停止したため送らなかった)のいずれかです。
上限と料金
| 項目 | 内容 |
|---|---|
| 月間の含まれる通数 | プランに含まれます(Free 100・Basic 1,000・Pro 3,000、アプリごと、毎月1日(韓国時間)にリセット)。含まれる通数は追加料金なしです |
| 含まれる通数を超えた分 | 無料プランでは翌月1日まで送信が止まります。有料プランでは、コンソールで追加送信をオンにした場合にだけ、1通1ウォン(KRW)(VAT別、VAT込み1.1ウォン)で送信を続けます。メールサーバーが受け付けたメールだけを、送信直後にクレジットから差し引きます |
| 1日の上限 | デフォルトはアプリごとに500通(コンソールで1–5,000)。韓国時間の0時にリセットされます |
| 1分あたりの上限 | アプリごとに1分30通 |
エラー
| HTTP | コード | 説明 |
|---|---|---|
| 400 | MAIL_INVALID | 不正なリクエスト。reasonに理由が入ります(invalid_recipient、too_many_recipients、subject_invalid、advertising_not_allowed、body_required、attachment_type_not_allowed、attachments_too_largeなど) |
| 402 | insufficient_credit | 追加送信の支払いに必要なクレジットが足りない。何も送信されません |
| 403 | MAIL_APP_KEY_REQUIRED | アプリキーではないキーで呼び出した |
| 403 | APP_NOT_ACTIVE | キーに紐づくアプリが動いていない |
| 402 | MAIL_OVERAGE_UNPAID | 未払いの追加メール料金が残高を超えている。チャージすると未払い分が差し引かれ、送信が再開します(含まれる通数の範囲内の送信は引き続き使えます) |
| 403 | MAIL_EMAIL_UNVERIFIED | メール認証済みのコンソールアカウントがない |
| 403 | MAIL_SUSPENDED | スパム報告やバウンスの基準を超えたため、または運営者が停止したため、このアプリのメール送信が停止されている |
| 429 | MAIL_RATE_LIMITED | 1分あたりの上限を超えた。retryAfterSecondsの後に再送してください |
| 429 | MAIL_DAILY_CAP_EXCEEDED | 1日の上限を超えた。韓国時間の0時に再開します |
| 429 | MAIL_MONTHLY_LIMIT | 今月の含まれる通数を使い切った(無料プラン、または追加送信がオフ) |
| 503 | MAIL_UNAVAILABLE | メールサーバーが利用できない。しばらくしてから再試行してください |
Webメタバースにリアルタイムの訪問者数を付ける
Three.jsで作ったWebの3D空間や通常のWebページに「いまN人がオンライン」と表示する無料の機能です。コンソール > 訪問者数でサイトを登録すると、公開サイトキー(pk_presence_…)と1行のスクリプトが発行されます。キーやログインなしで、ブラウザから直接呼び出します。
- 許可オリジン:登録時に入力したアドレス(https、パスなし、最大5件)からの信号だけを数えます。サイトアドレスのドメインも許可オリジンに含まれている必要があります。
- 数え方:各タブが30秒ごとに信号を送り、直近75秒以内に信号を送ったタブを「オンライン」と数えます。タブが非表示になると信号を止め、閉じるとすぐに外れます。
- 水増しの防止:同じタブからの信号は1回として数え(10秒以内の繰り返しは無視)、1つのIPが追加できるタブ数やサイトごとの信号数にも上限があります。User-Agentが空の信号、自動化ツールやヘッドレスブラウザからの信号は数えません。
スクリプトを追加する
コンソール > 訪問者数で取得した1行のスクリプトをページに入れ、数字を表示したい場所にdata-hrum-onlineを付けてください。
<script src="https://hrum.ai/p/presence.js" data-key="pk_presence_YOUR_SITE_KEY" async></script>
<span data-hrum-online></span> online now
これで完了です。ページを開いた各タブがすぐに信号を送り、その後30秒ごとに送り、返ってきた訪問者数をdata-hrum-onlineの付いたすべての要素に入れます。数字が届くまでは空のままです。
- サイトキー(
pk_presence_…)は公開キーなので、ページのソースに入れても問題ありません。他のサイトが持ち出しても、許可オリジンからの信号でなければ数えられません。 - タブが見えていないとき(別のタブへの切り替えやアプリの最小化)は信号を止め、再び見えるようになるとすぐに1回送ります。タブを閉じたり離れたりすると退出の信号を1回送ります。その信号が届かなくても、75秒後には外れます。
- 同じタブで再読み込みしても1人として数えます。各タブはランダムなセッション値を作り、そのタブの
sessionStorageにだけ保存します。Cookieやログイン情報は送りません。 - キーが間違っていたりネットワークがブロックされていたりしても、エラーは出ず、数字が空のままになるだけです。スクリプトが2回追加されても(タグマネージャー+直接埋め込みなど)、先に起動した1つだけを使うため、二重に数えることはありません。
数字を自分で使う
スクリプトはwindow.HrumPresenceを作成します。3Dの看板やバッジなど、独自のUIに数字を描くときに使ってください。
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は数字が変わったときだけ呼ばれます。すでに数字が届いた後に登録すると、すぐに1回呼ばれます。スクリプトを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_… — Three.jsで作った小さな部屋に、「○ いまオンライン」バッジと3Dの看板を付けた例です。看板とテーブルの周りの人物は、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"}}
数字が表示されない場合は、現在のページのアドレス(オリジン)が許可オリジンに含まれているか確認してください。許可オリジンは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 | 自社サーバーから数字を送ります(下記)。サーバーキーが必要で、1分に1回。ルームごとの人数roomsも送れます |
GET /api/v1/partners/v1/presence/sites/{siteKey}/rooms | ルームサーバーが入室先のルームを選ぶためのルームごとの人数(下記)。サーバーキーが必要で、非公開 |
GET /api/v1/partners/v1/presence/directory | Metamoaへの共有に同意したサイトの一覧(名前・アドレス・訪問者数)。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_…)を発行してください。サーバーキーは発行時に1回だけ表示されるため、サーバーの環境変数に保存し、ページやブラウザのコードには絶対に入れないでください。再発行すると、以前のサーバーキーはすぐに使えなくなります。
POST /api/v1/partners/v1/presence/sites/{siteKey}/count・本文{ "online": integer }(0–100,000)・ヘッダーX-Presence-Secret: sk_presence_…またはAuthorization: Bearer sk_presence_…。レスポンス{ online, reportedAt }- サーバー間専用のため、ブラウザのCORSは開いていません。公開キー(
pk_presence_…)で送ると401を返します。 - サイトごとに1分に1回まで受け付けます。それより頻繁に送ると、
Retry-After(秒)付きで429を返します。 - 直近5分以内に自社サーバーが値を送っていれば、その値を訪問者数として使います(
source: "server")。5分を過ぎるとスクリプトの信号の集計に戻ります(source: "beacon")。信号もなければ0です。 - 値が前回より急に大きく跳ね上がっても、そのまま表示しますが、運用確認のために記録します。
- 本文には
onlineと下のroomsだけを入れてください。それ以外のフィールドがあると400を返します。
ルームごとの人数(任意)
自社サーバーが人をルーム(チャンネル、インスタンス)に分けている場合は、同じcountの本文でルームごとの人数と定員を送れます。ルームサーバーは、新しく入る人をどのルームに入れるか選ぶときにGET …/roomsで読み戻します。ルームごとの数字はサーバーキーでのみ読み取れ、公開の照会(online・directory)やpresence.jsには表示されません。全体の訪問者数はこれまでどおりonlineで別に送ってください(ルームの合計からは計算しません)。
POST /api/v1/partners/v1/presence/sites/pk_presence_…/count
X-Presence-Secret: sk_presence_…
Content-Type: application/json
{
"online": 98,
"rooms": [
{ "id": "studio-1", "n": 30, "cap": 30 },
{ "id": "studio-2", "n": 28, "cap": 30 },
{ "id": "studio-3", "n": 40, "cap": 50 }
]
}
// 200
{ "success": true, "data": { "online": 98, "reportedAt": "2026-10-31T09:00:00.000Z" } }
roomsは最大200件です。idは英字、数字、_、-からなる1–64文字(#や空白は不可)で、1つの本文の中で重複してはいけません。nは0–100,000の整数、capは1–100,000の整数です。ルームのオブジェクトにそれ以外のフィールドがあると400を返します。nがcapより大きいと400PRESENCE_ROOM_OVER_CAPになります。定員を超えて人を受け入れないのはルームサーバーの役割なので、超過した値は保存しません。その他の形式エラーはfield付き(例:rooms[3].id)の400PRESENCE_BAD_REQUESTを返します。400の場合は全体の数字も保存しません。- 報告のたびにルーム一覧全体を置き換えます。次の報告にないルームは消え、
roomsのない報告はルームがないものとして扱います。 - 最後の報告から2分間新しい報告がなければ、ルーム一覧は空の一覧(
[])として読み取られます。これは全体の数字の5分ルールとは別です。毎分報告すれば消えません。 - 1分に1回の上限(429)で拒否された報告も、ルーム一覧を変更しません。
GET /api/v1/partners/v1/presence/sites/pk_presence_…/rooms
Authorization: Bearer sk_presence_…
// 200
{ "success": true, "data": {
"rooms": [
{ "id": "studio-1", "n": 30, "cap": 30, "free": 0 },
{ "id": "studio-2", "n": 28, "cap": 30, "free": 2 },
{ "id": "studio-3", "n": 40, "cap": 50, "free": 10 }
],
"reportedAt": "2026-10-31T09:00:00.000Z"
} }
- ヘッダーは
countと同じです(X-Presence-SecretまたはAuthorization: Bearer)。そのサイトのサーバーキーだけを受け付けます — 公開キー、他のサイトのサーバーキー、キーなしは401、無効化したサイトは404を返します。 roomsはidの数字順に並びます(studio-2がstudio-10より前)。free=cap − nです。番号の小さいルームから埋めたい場合は、free > 0の最初のルームを選んでください。reportedAtは最後に受け取った報告の時刻です(一度もなければnull)。2分経ってルーム一覧が空になっても、この値で最後の報告がいつ来たかがわかります。- サーバー間専用のため、ブラウザのCORSは開いておらず、レスポンスはキャッシュされません(
Cache-Control: no-store)。サイトごとに1分60回まで。それを超えるとRetry-After付きで429を返します。 - 受け付けるのはルームIDと人数・定員の数字だけです。ユーザー情報は入れないでください。
サーバーキーは自社サーバーにだけ置いてください。sk_presence_…がブラウザのコード、アプリ、公開リポジトリに入ってしまうと、誰でも訪問者数を変更できてしまいます。環境変数やシークレットストアに入れ、漏れた場合はコンソール > 訪問者数ですぐに再発行してください。
1分に1回送ってください。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()するチャンネルに参加してプレゼンスのキーを数えて数字を送り、pg_cronがそれを毎分呼び出します。キーは接続ごとに1つなので、1人を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'))
);
$$);
Metamoaへの共有
コンソールで「Metamoaのディレクトリに表示する」をオンにすると、サイトの名前・アドレス・現在の訪問者数が、MetamoaなどHRUMが運営するディレクトリに表示されます。サイトアドレスが許可オリジンと一致しない場合は表示されません。いつでもオフにできます。
プライバシー
- 訪問者のIPアドレスとUser-Agentは保存しません。IPは不正防止の計算のためにメモリ上で短時間使うだけで、ログには残しません。
- サーバーが保持するのは、セッションのハッシュ
sha256(siteKey + ":" + sid)と最後の信号の時刻だけで、10分後に削除します。Cookieは使いません。 - 「オンライン」は、直近75秒以内に信号を送ったタブの数です。
エラー
| HTTP | コード | 説明 |
|---|---|---|
| 400 | PRESENCE_BAD_REQUEST・INVALID_BODY | siteKeyまたはsidの形式が不正、または本文がJSONではない |
| 401 | PRESENCE_SECRET_REQUIRED | サーバーキーがない、または間違っている(公開キーを送った場合を含む) — countのみ |
| 403 | PRESENCE_ORIGIN_NOT_ALLOWED | Originがない、または許可オリジンではない |
| 404 | PRESENCE_SITE_NOT_FOUND | 不明なキー、または無効化されたキー |
| 413 | PAYLOAD_TOO_LARGE | 本文が1KBを超えている |
| 429 | PRESENCE_RATE_LIMITED | 信号が多すぎる、または1分以内にcountを再送した(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=…)は認証を行わず、https://console.hrum.ai/verify-email.html?token=…へ302でリダイレクトするだけです — そのページでパスワードを入力すると、上記のPOSTが呼び出されます。
AIでコンソールを管理
Claude Code、Cursor、CodexなどのAIコーディングツールに、コンソール作業を任せられます。AIは照会をすぐに行えますが、状態を変える操作 — キーの発行、チャージリンク、ホスティングの申し込み — は、人がコンソールの同意画面で「同意」を押した後にのみ進みます。サーバーは同意コードのない書き込みを拒否するため、人の同意を飛ばす経路はありません。唯一の例外は下記のhosting_opsで、発行時に人がチェックしたトークンでのみ有効です。
コンソール管理トークン
- AIが使う専用トークンです(
hrum_cm_で始まります)。リクエストヘッダーAuthorization: Bearer hrum_cm_…で送ります。 - デフォルトの権限は読み取り専用です(アカウント · キー一覧 · クレジット · 利用量 · ホスティング · 精算状況)。4つの書き込み権限 —
keys(APIキーの発行・再発行・失効)·credit(チャージリンク、返金プレビュー)·hosting(ホスティングの申し込みと解約)·seller(販売者登録リンク)— は、発行時の同意画面で人が1つずつチェックします。 hosting_ops(AI運用トークン — ホスティング中のアプリの環境変数の設定・削除、デプロイの開始とデプロイ状況の確認、ロールバックと再起動、実行ログの確認)も、発行時の同意画面でチェックします。この権限は操作のたびに改めて同意を求めません。環境変数・シークレットの設定方法とAI経路で許可される名前はRIDM Appsデプロイガイド — AIでシークレットを設定に、デプロイの開始とデプロイ状況・ログの確認方法はAIでデプロイしてログを確認にあります。- トークンの有効期間は30日です。1アカウントにつき、有効なトークンは最大10個までです。
- コンソールのAPIキー画面にある「AIコンソール管理トークン」一覧で、各トークンのプレフィックス・権限・最終使用日時を確認でき、いつでもすぐに失効させられます。トークンの値自体は二度と表示されません。
同意の流れ
- AIは実行したい内容(何を · 金額 · 対象)を指定して
POST /api/v1/partners/v1/console-ai/consentsを呼び出し、consentUrlとcodeを受け取ります。 - AIはそのリンクをユーザーに見せます(MCPならブラウザで開くこともできます)。
- ユーザーがコンソールにログインした状態でリンクを開くと、リクエスト内容がすべて(金額 · 対象 · 名前)「AIによるリクエスト」ラベル付きで表示されます。ユーザーは内容を確認して「同意」を押します。支払い自体も、その後Toss決済画面で人が行います。
- AIは
GET /console-ai/consents/{code}で承認を確認し、書き込みリクエストの本文にconsentCodeを入れて処理を続けます。
同意コードは1回だけ使え、10分で期限切れになります。コードにはリクエストのハッシュが固定されているため、同意後に金額や対象を変えるとリクエストは拒否されます(CONSENT_MISMATCH)。
最初のトークンはまだトークンがないため、認証なしで{"action":"token_issue","payload":{"scopes":["keys"]}}を使ってリクエストします。レスポンスのpollSecretをX-Consent-Poll-Secretヘッダーに入れて状況を確認します。トークンの値は、承認後の最初の確認時に1回だけ返されます。同じレスポンスの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}) | その操作の権限(最初のトークンはなし) | — |
GET /consents/{code} | 同意の状況:pending · approved · denied · expired · used | read(最初のトークンはpoll secret) | — |
GET /me · GET /token | 自分のアカウント · このトークンの権限 | read | — |
GET /status | はじめにチェックリスト(API · ホスティング · 決済の状況と次のステップ) | read | — |
GET /keys | APIキー一覧(プレフィックスのみ) | read | — |
GET /credit · GET /credit/transactions | クレジット残高 · 履歴(offset、limit ≤ 100) | read | — |
GET /usage | 期間別の呼び出し数と利用額(from、to) | read | — |
GET /hosting | ホスティングの利用資格 · プラン · アプリの状況 | read | — |
GET /seller · GET /payouts | 販売者の状況(本人確認情報を除く)· 精算履歴 | read | — |
POST /keys | APIキーを発行({label?}) | keys | key_issue |
POST /keys/{id}/rotate | 新しいキーを発行+このキーを即時無効化 | keys | key_rotate |
POST /keys/{id}/revoke | キーを失効(元に戻せません) | keys | key_revoke |
POST /credit/topup-link | チャージ決済リンク({planKey}) | credit | credit_topup_link |
POST /credit/refund-preview | 返金可能額を計算(返金は申請しません) | credit | credit_refund_preview |
POST /hosting/apply | ホスティングを申し込む({planKey, subdomain, recurringConsent?}) | hosting | hosting_apply |
POST /hosting/apps/{id}/cancel | ホスティングを解約 | hosting | hosting_cancel |
POST /seller/apply-link | 販売者登録画面へのリンク | seller | seller_apply_link |
書き込みリクエストの本文は、同意リクエストのpayloadと同じ値+consentCodeです。新しいAPIキーは、そのレスポンスで1回だけ表示されます。
カード番号と販売者の本人確認情報は、AI経路では一切受け付けません。カード決済はToss決済画面で行い、販売者の本人確認情報・口座・規約への同意は人がコンソール画面で入力します。payloadに定義済みフィールド以外の値が含まれている場合は、400 UNKNOWN_FIELDで拒否されます。
エラーコード
| コード | HTTP | 意味 |
|---|---|---|
MGMT_TOKEN_INVALID | 401 | トークンがない、期限切れ、または失効済み。新しく取得してください |
MGMT_SCOPE_DENIED | 403 | このトークンに必要な書き込み権限がありません(scopeフィールド)。その権限にチェックを入れて新しく発行してください |
ACCOUNT_SUSPENDED | 403 | 停止中のアカウント |
CONSENT_REQUIRED | 400 | 書き込みリクエストにconsentCodeがない |
CONSENT_PENDING | 409 | 人がまだ同意していない |
CONSENT_DENIED | 403 | 人が拒否した |
CONSENT_EXPIRED | 410 | 10分が過ぎて期限切れ |
CONSENT_USED | 409 | 同意コードは使用済み |
CONSENT_MISMATCH | 409 | 現在のリクエストが同意した内容(金額 · 対象)と異なる |
CONSENT_NOT_FOUND | 404 | 不明なコード、または別アカウントのコード |
INVALID_CONSENT_PAYLOAD | 400 | payloadの値が不正(fieldフィールド) |
UNKNOWN_FIELD | 400 | AI経路で受け付けないフィールドが含まれている |
CONSENT_RATE_LIMITED | 429 | 同意リクエストが多すぎる |
MGMT_TOKEN_LIMIT | 409 | 有効なトークンがすでに10個あるため、これ以上発行できない |
NOT_AVAILABLE | 404 | まだ公開されていないメニュー |
MCPから使う
HRUM MCP(@hrum/mcp 0.2.0)をインストールすると、上記の流れをそのままツールとして使えます。トークン・APIキー・poll secretはモデル(会話)に一切現れず、このコンピューターの設定フォルダと.env.localにのみ保存されます。
claude mcp add hrum -- npx -y https://console.hrum.ai/mcp/hrum-mcp-0.3.6.tgz
| ツール | 内容 |
|---|---|
hrum_ai_connect · hrum_ai_connect_status | 管理トークンの同意リンクを作成 → 承認されたらトークンを保存(値は表示されません) |
hrum_status · hrum_keys_list · hrum_credit · hrum_credit_history · hrum_usage · hrum_hosting_status · hrum_seller_status · hrum_payouts_list | 照会 |
hrum_consent_request · hrum_consent_status | 書き込みへの同意をリクエスト · 状況を確認 |
hrum_key_issue · hrum_key_rotate · hrum_key_revoke | キーの発行・再発行(新しいキーは.env.localにのみ保存)· 失効 |
hrum_topup_link · hrum_refund_preview | チャージリンク · 返金可能額 |
hrum_hosting_apply · hrum_hosting_cancel · hrum_seller_apply_link | ホスティングの申し込みと解約 · 販売者登録リンク |
アカウント照会API
クレジット残高と利用量を確認するためのAPIです。ヘッダーにX-Partner-Api-Keyを含める必要があります。
GET /api/v1/partners/v1/credits/balance
現在のクレジット残高を取得します。
リクエスト
curl -X GET https://api.hrum.ai/api/v1/partners/v1/credits/balance \
-H "X-Partner-Api-Key: your-api-key"
レスポンス
{
"success": true,
"data": {
"balanceWon": 25000,
"lastUpdated": "2026-10-09T05:12:30.000Z",
"estimatedMonthEndBalance": 15000,
"warningThreshold": 5000,
"lowBalanceActive": false
}
}
warningThresholdはパートナーごとに異なります — max(₩5,000、直近の有料チャージ額の20%)。lowBalanceActiveは、残高がこのしきい値を下回り、残高不足の警告が有効になっているかどうかを示します。APIでチャージするエンドポイントはありません — コンソール > 請求でチャージしてください。このAPIには固有のエラーコードはなく、共通エラーのみです。
GET /api/v1/partners/v1/usage/logs?limit=50&offset=0
API呼び出しの記録を新しい順に取得します。各項目にはid · timestamp · endpoint(短い名前、例:manseryeok)· statusCode · costWon · responseTimeMs(現在は常にnull)があり、該当する場合はidempotencyKey · model · endUserId · cachedTokensも含まれます。
リクエストパラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
limit |
number | 取得する件数(デフォルト:50、最大:200) |
offset |
number | オフセット(デフォルト:0) |
endpoint |
string | エンドポイントの短い名前で絞り込み(例:manseryeok)。allまたは省略ですべて |
dateFrom · dateTo |
string | 期間(YYYY-MM-DD)。省略すると制限なし |
リクエスト
curl "https://api.hrum.ai/api/v1/partners/v1/usage/logs?limit=50&offset=0&endpoint=manseryeok" \
-H "X-Partner-Api-Key: your-api-key"
レスポンス
{
"success": true,
"data": {
"logs": [
{
"id": "12345",
"timestamp": "2026-08-10T14:30:00.000Z",
"endpoint": "manseryeok",
"statusCode": 200,
"costWon": 50,
"responseTimeMs": null,
"idempotencyKey": "order-8812"
}
],
"total": 1234,
"pagination": {
"limit": 50,
"offset": 0,
"hasMore": true
}
}
}
GET /api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31
期間ごとの利用統計を取得します。日付を省略すると、当月全体が対象です。dailyBreakdownの日付は韓国時間(KST)です。
リクエストパラメータ
| パラメータ | 型 | 説明 |
|---|---|---|
dateFrom |
string | 開始日(YYYY-MM-DD) |
dateTo |
string | 終了日(YYYY-MM-DD) |
リクエスト
curl "https://api.hrum.ai/api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31" \
-H "X-Partner-Api-Key: your-api-key"
レスポンス
{
"success": true,
"data": {
"dateRange": { "from": "2026-08-01", "to": "2026-08-31" },
"totalCalls": 1234,
"totalCostWon": 6170,
"byEndpoint": [
{
"endpoint": "manseryeok",
"calls": 1234,
"costWon": 6170,
"percentOfTotal": 100
}
],
"dailyBreakdown": [
{
"date": "2026-08-10",
"calls": 150,
"costWon": 750
}
]
}
}
エラーコード(利用ログ · 集計)
共通エラーのほかに、YYYY-MM-DD形式でない日付や、負のlimit・offsetはコードなしの400を返します。照会は無料です。
GET /api/v1/partners/v1/status/upstream
HRUMが利用しているAIプロバイダー(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
認証なしで万歳暦(韓国の四柱推命の暦)を計算します。ゲスト用エンドポイント(万歳暦 · ネイタルチャート)は、IPごとに月5回の無料枠を共有します。超えると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は有料APIと同じように適用され、旧暦で入力するとlunarInputが追加されます。体験版のため、langによる翻訳、glossary、identity、ohaengDeficientは含まれません。timezoneが認識できない場合は、有料APIと同じくwarningsが追加されます。
{
"success": true,
"data": {
"wonkuk": {
"year": { "stem": "기", "branch": "사", "stemHanja": "己", "branchHanja": "巳", ... },
"month": { ... }, "day": { ... }, "hour": { ... }
},
"trueSolarTime": null,
"ohaengBalance": { ... },
"yongshin": "...",
...,
"guestRemaining": 4
}
}
上限超過(429)
{
"success": false,
"statusCode": 429,
"code": "GUEST_QUOTA_EXCEEDED",
"message": "게스트 체험 한도(월 5회)를 초과했어요. API 키를 발급받아 사용해주세요.", // "Guest trial limit (5 per month) exceeded. Please get an API key."
"timestamp": "..."
}
エラーコード
| HTTP | コード | 発生条件 |
|---|---|---|
| 429 | GUEST_QUOTA_EXCEEDED | 同じIPから今月5回を超えて呼び出した(ネイタルチャートのゲスト用エンドポイントと合算) |
| 400 | INVALID_LUNAR_DATE · INVALID_LOCATION | 存在しない旧暦の日付 / 緯度と経度の片方だけを送った。これらも1回分として数えられます |
| 400 | (なし) | 本文の検証に失敗(共通エラーと同じ) |
POST /api/v1/partners/v1/playground/natal-chart
認証なしでネイタルチャートを計算します。リクエスト本文は有料の/natal-chartと同じで、レスポンスは同じチャート+guestRemainingです。解説文(readings)は提供されません。回数枠は万歳暦のゲスト用エンドポイントと共有です(IPごとに月5回)。
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、それ以外は共通エラーと同じです。
有効な値
天干(チョンガン)
갑(甲)、을(乙)、병(丙)、정(丁)、무(戊)、기(己)、경(庚)、신(辛)、임(壬)、계(癸)
地支(チジ)
자(子)、축(丑)、인(寅)、묘(卯)、진(辰)、사(巳)、오(午)、미(未)、신(申)、유(酉)、술(戌)、해(亥)
五行(オヘン)
목(木)、화(火)、토(土)、금(金)、수(水)
言語に依存しないコード値
以下のフィールドは、langを送っても韓国語のコード値のままです。表示名ではなく、分岐や照合に使う値です。表示名には、同じレスポンスの翻訳済みフィールド(primaryLabel · signEnなど)か、万歳暦のglossary: true用語集を使ってください。値は上記の天干・地支・五行と、通変星(비견 比肩 · 겁재 劫財 · 식신 食神 · 상관 傷官 · 편재 偏財 · 정재 正財 · 편관 偏官 · 정관 正官 · 편인 偏印 · 정인 正印)です。
- 万歳暦 —
wonkuk.*.stem·branch·ohaeng、daeun[]·seun[]のstem·branch·ohaeng、ohaengBalanceのキー、cheonganDetail.seasonal.monthBranch、yongshinDetail.element_statesのキー、byeongyak.primary·tonggwan.primary(五行コード — 表示名はprimaryLabel)、jeongtak.verdictの「청」(清)· 「탁」(濁)(「판정불가」(判定不可)のみ翻訳されます)、glossaryのキー - 万歳暦
identity· Saju Identity —saju.{year,month,day,hour}.{cheongan,jiji,ohaeng}、timeline(current · daeunChain · years · highlights)のstem·branch·ohaeng·ganji、gongmang.void_branches[]·gongmang.hits[].jiji、samjae.current_year_branch、season_strength_hint.yongshin_hint.primary[]·secondary[]、sinsal_list[].id(例:sinsal12_재살)、yongshin.element_statesのキー、sipsin_map.* - 万歳暦
astrology: true—natalChart.bodies[].sign·element(英語はsignEn)— ネイタルチャートAPIと同じ表記 - 今日の運勢 —
summary.day_master(例:「계」 癸)、summary.ilju(「계미」 癸未)、summary.today_day_ohaeng、summary.yongshin、omen.color.ohaeng - 運勢フロー — 干支の読み、五行名と関係名、
chars[].sipsin、natal.level·natal.result(日干の強弱判定、例:「약약」(弱)· 「중화」(中和))、natal.primaryYongshin·natal.shin.*、triples[].element、compatInputs.*(surfaceElementCountsのキーを含む) - 相性 —
saju.personA/B.ilju、dictionary.a/b.id(ilju_경진)·name_kr、yearFlow.years[].a/bのstem·branch·ohaeng·relations[].target·type、saju.full8.personA/B.elementDistribution·sipsinCount·combinedElementBalance.distributionのキー
率直さ(candor)
t、f(デフォルト)— 大文字と小文字は区別しません。旧値のbluntはtに、balanced · gentleはfに正規化されます。それ以外の値は400を返します(率直さ(仮称))
エラーコード
すべてのAPIは、以下の共通エラーを同じ形で返します。各APIセクションのエラー表には、そのAPI固有のコードだけを載せています。リクエストは次の順に確認され、あるステップで失敗すると、それ以降のステップは実行されません。
- セキュリティルール — ブロック対象のUser-AgentはAPIサーバーに届く前に遮断されます(403、HTML本文、error 1010)。APIキーの確認より前に起きるため、401ではなく403になります
- サービス保護上限 — 同じIPからの全リクエストに対する1分あたりの上限(429、
codeなし) - APIキー —
X-Partner-Api-Keyの確認(401) - 機能の有効化 — アカウントで有効になっていない機能(404
*_not_enabled) - リクエスト制限 — コンソールで設定した1秒あたり・1日あたりの制限(429
RATE_LIMIT_EXCEEDED) - 本文の検証 — フィールド名、型、範囲(400)
- 残高 · 計算 · 呼び出し — 残高不足(402)、API固有の入力エラー、外部モデルのエラー
共通エラー
| HTTP | コード | 発生条件 | 課金 |
|---|---|---|---|
| 400 | (なし) | 本文の検証に失敗 — 表にないフィールドを送った、または型や範囲が誤っている。messageは文字列の配列です | なし |
| 401 | (なし) | X-Partner-Api-Keyがない、無効なキー、失効済みのキー、無効なアカウント | なし |
| 402 | INSUFFICIENT_BALANCE | クレジット残高不足。ストリーミングレスポンスでは、event: errorに同じcodeとstatusが入ります | なし |
| 402 | (なし) | 差し引く時点で残高が足りなかった(呼び出し前に残高を確認しないAPI、または呼び出し中に別のリクエストが残高を使った場合)。messageに必要額と残高が入ります | なし |
| 403 | (HTML本文) | セキュリティルールによるブロック(error 1010)— デフォルトのUser-AgentがブロックされているHTTPクライアント。クイックスタートのUser-Agentに関する注意を参照してください | なし |
| 404 | *_not_enabled | アカウントで有効になっていない機能(例:ziwei_not_enabled、dream_not_enabled) | なし |
| 404 | (なし) | 不明なパス。本文のmessageは"Not Found"だけです | なし |
| 429 | (なし) | サービス保護上限を超過(APIキーごとに1分あたり300回など)。Retry-Afterはありません — 1分以内に再試行してください | なし |
| 429 | RATE_LIMIT_EXCEEDED | コンソールで設定した1秒あたりまたは1日あたりの制限を超過。本文にretryAfterSecondsがあり、Retry-Afterヘッダーも付きます | なし |
| 500 | (なし) | サーバーエラー。このリクエストですでに差し引かれた金額は、レスポンスの後に返却されます | 返金 |
| 503 | SERVICE_DEGRADED | 一時的なデータベース接続の問題。Retry-After: 30 — 30秒後に再試行してください | 返金 |
エラーレスポンス本文の形式:{"success": false, "statusCode": 400, "code": "INVALID_LOCATION", "message": "...", "timestamp": "..."} — codeはある場合にのみ含まれます。分岐にはstatusCodeとcodeを使い、messageの文言には頼らないでください。
// 401 — key missing or invalid
{ "success": false, "statusCode": 401, "message": "Invalid or missing API key", "error": "Unauthorized", "timestamp": "2026-10-12T03:00:00.000Z" }
// 400 — body validation failed (message is an array)
{ "success": false, "statusCode": 400, "message": ["property foo should not exist", "month must not be greater than 12"], "error": "Bad Request", "timestamp": "2026-10-12T03:00:00.000Z" }
// 404 — feature not enabled for the account (message: "This feature is not available yet")
{ "success": false, "statusCode": 404, "code": "ziwei_not_enabled", "message": "아직 열리지 않은 기능입니다", "timestamp": "2026-10-12T03:00:00.000Z" }
// 429 — request limit set in the console (message: "Per-second request limit exceeded. You can adjust it in console > API keys > Request limits.")
{ "success": false, "statusCode": 429, "code": "RATE_LIMIT_EXCEEDED", "message": "초당 요청 제한을 초과했어요. 콘솔 > API 키 > 요청 제한에서 조정할 수 있어요.", "retryAfterSeconds": 1, "timestamp": "2026-10-12T03:00:00.000Z" }
よく見られるAPI固有のコード:422 処理できない入力(PROMPT_TOO_LONG、EXTRACTION_FAILED)、503 一時的に利用不可(例:解説文を読み込めなかった場合。課金なし)、504 外部モデルのタイムアウト。ゲスト体験の回数枠は429 GUEST_QUOTA_EXCEEDEDです。
レスポンスの警告(warnings)
リクエストは成功したものの、入力の一部が認識できずデフォルト値を使った場合、成功レスポンスのdataのトップレベルの末尾にwarnings配列が追加されます。ステータスコードは200のままで、料金も同じです。警告がなければwarningsキーはありません — レスポンスはこれまでとまったく同じです。各項目は{"code", "field"}だけで、送った値(出生データ)は返されません。同じ問題が複数のフィールドに及ぶ場合は、フィールドごとに1項目ずつ入ります。
| コード | 意味 | フィールド |
|---|---|---|
UNKNOWN_TIMEZONE | タイムゾーン名が認識できなかったため、デフォルトのタイムゾーンを使いました。入力ミスを確認してください(例:Asia/Seol)。省略または空の場合は警告は出ません | 万歳暦 · Saju Identity · 四柱推命 ↔ MBTI比較 · 今日の運勢 · 生涯四柱 · ゲスト用万歳暦のtimezone、KB解説のbirth.timezone、相性のpersonABirthTimezone · personBBirthTimezone |
// 200 — calculated with the default time zone, only a warning is added
{ "success": true, "data": { "wonkuk": { ... }, ..., "warnings": [ { "code": "UNKNOWN_TIMEZONE", "field": "timezone" } ] } }
レート制限
サービス保護上限は常に適用されます:APIキーごとに1分あたり300回(同じIPからのキー付きリクエスト全体で1分あたり3,000回)。超えるとcodeもRetry-Afterもなしで429が返ります — 少し待って(1分以内に)再試行してください。これより低い制限はパートナーが設定します — キーの流出や無限ループから残高を守るため、コンソールのAPIキー > リクエスト制限で1秒あたりのリクエスト数と1日あたりのリクエスト数(KST)を設定してください。空欄のままにすると、上記のサービス保護上限のみが適用されます。
- 制限を設定すると、レスポンスに
X-RateLimit-Limit-Second/X-RateLimit-Remaining-Second/X-RateLimit-Limit-Day/X-RateLimit-Remaining-Dayヘッダーが付きます。 - パートナーが設定した制限を超えると、
429+{"code":"RATE_LIMIT_EXCEEDED","retryAfterSeconds":N}とRetry-Afterヘッダーが返ります。ブロックされたリクエストは課金されません。 - ゲスト(キーなし)は、月5回の無料テスト呼び出しに固定されています。
課金
すべてのAPI呼び出しはクレジットから差し引かれます。新規登録すると₩1,000分の無料クレジットが付与されます(不正防止の条件に該当した場合は付与が保留されることがあります)。ゲストは月5回まで無料でテストできます。
| API | 料金 |
|---|---|
| manseryeok(万歳暦) | 1回あたり₩50 |
| compat(相性) | 1回あたり₩20 |
| lifetime(生涯四柱) | 全体 1回あたり₩100 · 1テーマ 1回あたり₩20 · 星座/紫微斗数レイヤー 1レイヤーにつき+₩20 |
| ziwei-chart(紫微斗数命盤) | 1回あたり₩50 · readings: true +₩20(合計₩70) |
| identity(Saju Identity、旧エンドポイント) | 1回あたり₩10 — 新しく連携する場合は、万歳暦のidentityフィールドを使ってください(追加料金なし) |
| saju-mbti(四柱推命 ↔ MBTI比較) | 1回あたり₩10(Saju Identityと同じ料金) |
| today(今日の運勢) | 1回あたり₩10 |
| dream(夢占い) | 1回あたり₩30(結果がない場合は₩0) |
| natal-chart(ネイタルチャート) | 1回あたり₩20 · readings: true 1回あたり₩40 |
| personality-type(性格タイプ)- 無料 | ₩0(無料) |
| personality-type(性格タイプ)- プレミアム | 1回あたり₩10 |
| reading(AI四柱推命リーディング) | トークン課金(使用トークン数により変動) |
| image(四柱推命画像) | 1枚あたり₩200 |
| image_generation(画像生成 · モデル再販) | モデル・解像度・品質ごとの1枚あたり固定料金 — 料金表 |
ゲストテスト
- 万歳暦とネイタルチャートのゲスト用エンドポイント:合算で月5回まで無料(IPで制限)
- ログインせずにプレイグラウンドでテスト
- 残り回数はレスポンスに含まれます(guestRemaining)
冪等性
成功したリクエストはすべて個別に課金されます。同じリクエストを再送すると、再計算・再生成されて再び課金されるため、再試行による重複や同じ入力の再利用には、クライアント側でレスポンスを保存して対応してください(例:リクエストのハッシュをキーにしたキャッシュ)。
X-Idempotency-Keyヘッダー(最大128文字 — それより長い場合は先頭128文字が記録されます)は引き続き受け付けますが、課金を防ぐものではありません。送ったキーは利用ログのidempotencyKeyにそのまま記録されるため、どのリクエストがどの呼び出しで処理されたかを、自社の注文IDやジョブIDと照合するのに使えます。
例外:人相・手相占いでは、同じキーと同じ本文を24時間以内に再送すると、新たに課金されずに最初の結果が返ります(再試行と再送信)。
例外:姓名分析では、同じキーと同じ本文を24時間以内に再送すると、新たに課金されずに最初の結果が返ります(再試行と再送信)。
サポート
連携中に行き詰まったときや、レスポンスがドキュメントと異なるときはお知らせください。
| お問い合わせ | 連絡先 |
|---|---|
| 技術サポート · 障害報告 · 提携 | contact@float.do |
お問い合わせの際に以下も送っていただくと、より早く確認できます。
- 呼び出したエンドポイントと日時(タイムゾーンを含む)
- APIキーの先頭12文字(
float_live_を含む。キー全体は絶対に送らないでください) - 受け取ったレスポンスのHTTPステータスコードと本文
規約と個人情報の取り扱いについては、利用規約(韓国語)とプライバシーポリシー(韓国語)をご覧ください。