APIガイド

このAPIスタックが実際のサービスでどう動くか気になりますか? 同じエンジンで動くAI四柱推命(サジュ)アプリ INTA – Life is Timing で、四柱推命分析とAIチャットを試せます。 INTAはこのAPIの実稼働リファレンスです。 INTAのAI音声応答(TTS)も同じスタックで動いています — 音声APIは今後提供予定です。

クイックスタート

HRUMは、記憶するAI・四柱推命分析・LLM再販を提供しています。次の3ステップで始められます。

ベースURLは https://api.hrum.ai(API)と https://console.hrum.ai(コンソール)です。旧アドレスの api.float.do、console.float.do、api.inta.do も引き続き使えるため、すでに連携済みの場合は変更不要です。

  1. APIキーを取得する - コンソールに新規登録し、APIキー画面でキーを作成します(キーは作成直後に一度だけ表示されます)。新規登録からエラー処理までの全手順は開発者向け「はじめに」ガイドにあります。
  2. リクエストを送る - 下の例に沿ってPOSTリクエストを送ります。
  3. レスポンスを処理する - JSONレスポンスから四柱推命データを取り出します。
curl -X POST https://api.hrum.ai/api/v1/partners/v1/manseryeok \
  -H "X-Partner-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "year": 1990,
    "month": 1,
    "day": 15,
    "hour": 14,
    "minute": 30,
    "timezone": "Asia/Seoul",
    "gender": "male"
  }'

User-Agentに注意: 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再販を提供しています。

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_FLAGGED400モデレーションでブロック(ridm:system+user、再販:userメッセージ)
INSUFFICIENT_BALANCE402残高不足(要求した出力全体を先に確保して確認)
MODEL_NOT_FOUND400モデルが設定されていません
INVALID_TOOLS / TOOLS_UNSUPPORTED_FOR_MODEL400toolsフィールドの不整合 / Claudeモデルでツール呼び出しを要求
FILE_NOT_FOUND400fileIds に存在しない(または他のパートナーの)ファイルが含まれています
FEATURE_DISABLED403その機能をオフにしたアカウントでyoutube・files・emotionオプションを使用
RATE_LIMITEDHTTP 400、本文の status 429アップストリームのレート制限、または1日の再販利用上限を超過(デフォルト:パートナーごとに₩100,000/日)
UPSTREAM_TIMEOUTHTTP 400、本文の status 504アップストリームの応答がタイムアウト(60秒)
UPSTREAM_INVALID_REQUEST400アップストリームのモデルがリクエストを拒否(upstream 400/422)
INVALID_RESPONSE_FORMAT400response_format: json_object なのにメッセージに「json」という単語がない(OpenAI系)
REPORT_ONLY_MODEL400ridm/saju-report が指定されました — 四柱推命レポートAPI専用です
(なし)400ridm/* モデルで user がない・systemPrompt が8,000文字超・未対応のモデルプレフィックス
provider_not_configured503現在Claudeモデルに接続されていません

補足

カスタムプロフィール

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固有のエラーコードはなく、共通エラーのみです。

制限と制約

LLM API(再販)

openai/*、google/* などの元のLLMモデルの再販です(メモリーなし、元のレスポンスそのまま)。再販モデルへのリクエストでは、user、systemPrompt、recallCount、memoryCap、summaryEvery、emotion、candor は無視され(システム指示は messages に {"role":"system"} として入れてください)、レスポンスにメモリーフィールド(recalledMemories など)は付きません。料金 = 原価 × 為替レート × 1.10。

利用可能なモデル(GET /api/v1/partners/v1/models と同じリスト)

curl https://api.hrum.ai/api/v1/partners/v1/models \
  -H "X-Partner-Api-Key: your-api-key"

GET /api/v1/partners/v1/models のレスポンス — 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)に対応しておらず、400 TOOLS_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解釈テキスト
sajuSourcecomputed(birthから計算) | provided(sajuの入力を使用)
sajuMismatchbirthと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 コード
400MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE · UNKNOWN_TOOL · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUND · INVALID_TOOL_MODE · MEMORY_REQUIRES_MEMORY_ENDPOINT · EMOTION_REQUIRES_MEMORY · MISSING_ENDUSER_ID(メモリー) · ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALID(AIを1つだけ使う)
402INSUFFICIENT_BALANCE — 呼び出し前に maxLength × 2 トークン分(valueプランまたは韓国語以外の質問では+4,000)の出力費用を先に確保するため、最終的な請求額がそれより小さくなる場合でも拒否されることがあります
403FEATURE_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)
夢占い dreamdream に夢を送ったとき夢のテキスト+夢の中で見つかったシンボル語/dream(候補がなければ ₩0)
タロット tarottarot を送ったときこのリクエストで引いたカードと正位置・逆位置の意味(画像URL付きで tarot に返ります)/tarot

リクエスト例(POST /api/v1/partners/v1/reading) — 夢占いの辞書は韓国語のみのため、夢のテキストは韓国語のままです

{
  "birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
  "question": "I can't stop thinking about last night's dream. What could it mean for me right now?",
  "dream": "큰 뱀이 집 안으로 들어와 내 발 옆에 똬리를 틀었어요",
  "tarot": { "spread": "past-present-future" }
}

レスポンス例

{
  "success": true,
  "data": {
    "interpretation": "뱀이 집 안으로 들어와 곁에 머무는 꿈은...",
    "sajuSource": "computed",
    "modulesUsed": ["saju", "dream", "ziwei", "astro", "tarot"],
    "moduleFees": { "dream": 30, "ziwei": 50, "astro": 20, "tarot": 20 },
    "tarot": {
      "lang": "ko",
      "count": 3,
      "spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
      "reversedAllowed": true,
      "seed": null,
      "cards": [
        { "position": 1, "positionLabel": "과거", "id": "wands_10", "name": "완드의 10", "nameEn": "Ten of Wands", "arcana": "wands", "reversed": true, "keywords": ["내려놓기", "위임", "해방"], "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.", "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp" }
      ],
      "cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp"
    },
    "usage": {
      "inputTokens": 3140,
      "outputTokens": 760
    },
    "costPoints": 162
  }
}

四柱推命のみ(他のモジュールをすべて外す)(POST /api/v1/partners/v1/reading)

{
  "birth": { "year": 1990, "month": 5, "day": 15, "hour": 14, "gender": "female" },
  "question": "Is this a good year to change jobs?",
  "exclude": ["ziwei", "astro"]
}

AIを1つだけ使う — only

四柱推命AIには、四柱推命・紫微斗数・西洋占星術・タロット・夢占いのAIが入っています。上のような1回の統合呼び出しの代わりに、only で必要なAIだけを呼び出せます。そのAIは自分の根拠(命式・ネイタルチャート・引いたカード・夢の候補)だけで答え、それ以外は加わりません。

only呼び出すもの必要な入力料金
saju四柱推命AI(四柱推命のみ、他のモジュールなし)birth または sajuトークン料金のみ(固定料金なし)
ziwei紫微斗数AIbirth+出生時刻(hour)トークン料金+/ziwei-chart 1回分
astro西洋占星術AIbirth(時刻は不要)トークン料金+₩20(西洋占星術モジュールの固定料金)
tarotタロットAItarot のオプション — birth は不要トークン料金+/tarot 1回分
dream夢占いAIdream に夢のテキスト — birth は不要トークン料金+/dream 1回分

リクエスト例 — タロット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
  }
}

補足

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コード発生条件
400MISSING_ENDUSER_IDendUserId が空、または空白のみ
400MISSING_SUBJECT_INPUT · INVALID_SAJU_PILLAR · INVALID_LUNAR_DATE出生データまたは四柱推命の入力エラー(リーディングAPIと同じ)
400UNKNOWN_TOOL · INVALID_TOOL_MODE · INVALID_FILE_IDS · FILE_IDS_TOO_MANY · INVALID_FILE_ID_TYPE · FILE_NOT_FOUNDtools または fileIds のエラー。このパスは tools.emotion と tools.summaryEvery も受け付けます
400ONLY_WITH_EXCLUDE · ONLY_REQUIRES_INPUT · ONLY_DOMAIN_UNAVAILABLE · ONLY_INPUT_INVALIDAIを1つだけ に関するエラー
402INSUFFICIENT_BALANCE出力コストを事前に確保できなかった(リーディングAPIと同じ方式)
403FEATURE_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コード発生条件
404END_USER_NOT_FOUND未知の endUserId(会話の保存以外の4つのパスで共通)
400MISSING_PARAM検索 — endUserId がない
400MISSING_TAGS検索 — tags が空
400ENDUSER_ID_TOO_LONG会話の保存 — endUserId が255文字を超えている

注意事項

四柱推命レポートAPI

ボタンひとつ、質問なしで、総評から財運・恋愛・大運まで四柱推命の全体リーディングを一度に提供します。会話型リーディングとは別の単発の有料商品です。デフォルトは専用モデル ridm/saju-report(レポートに特化したRIDM独自モデル — 単発の商品のためメモリーはありません)です。リーディングAPIのレスポンスは最大2,000文字です — より長い文章(最大12セクション、約6,000文字)が必要な場合は、このレポートAPIを使ってください。

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

生年月日(または四柱推命の命式)を送ると、セクションごとのMarkdownで四柱推命レポートが返ります。

リクエストパラメータ

パラメータ 型 必須 説明
birthobjectbirth または saju のいずれか{year, month, day, hour?, minute?, gender, calendar?} — calendar: "lunar" は計算前に新暦へ変換されます。出生地・タイムゾーン・閏月(2026-10-17):万歳暦APIと同じ任意フィールド — isLeapMonth、timezone、birthLatitude、birthLongitude、country、zaSiRule、birthTimePrecision — を同じ名前・同じルールで受け付けるため、同じ出生データからは万歳暦と同じ四柱が得られます。座標は両方送ってください。片方だけ送ると 400 INVALID_LOCATION が返ります。どれも送らない場合、計算は従来どおりです(出生時刻は韓国時間、旧暦は閏月でない月として扱います)。西洋占星術の部分は、その出生時点に timezone で実際に使われていた時計時刻(夏時間を含む)と座標からチャートを作成します。birth.timezone を認識できない場合、レスポンスに warnings(field: "birth.timezone")が含まれます
sajuobjectbirth または saju のいずれか四柱を直接入力します:{"year":{"stem":"경","branch":"오"},"month":{…},"day":{…},"hour"?:{…}}
year / month / day / gendernumber / string任意フラットなフィールド(旧形式、新暦)。4つすべてがそろっている場合のみ birth として受け付けます。birth も saju もない場合は 400 MISSING_SUBJECT_INPUT になります
hour / minutenumber任意hour を省略すると時柱を除き、年・月・日の三柱でリーディングします。hour なしで送った minute は無視されます
tonestring任意warm(デフォルト) | casual | formal
candorstring任意率直さ — t | f(デフォルト)。変わるのは長所と課題の配置と強さだけで、セクション構成や、医療・法律・投資について断定的に答えない方針はそのままです。料金はかかりません。率直さ(仮称)を参照
personastring任意話し方・キャラクターの指示(最大2,000文字 — この長さだけが入力として課金されます)
sectionsstring[]任意セクションタイトルのリスト(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)
  }
}

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
400MISSING_SUBJECT_INPUTbirth も saju も送られていない
400INVALID_SAJU_PILLARsaju の柱が六十干支のいずれでもない
400INVALID_LUNAR_DATE存在しない旧暦の日付
402INSUFFICIENT_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"
  }
}

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:

HTTPコード発生条件
400INVALID_YOUTUBE_URLURLから動画IDが見つからない
400TRANSCRIPT_UNAVAILABLE動画に字幕がない(課金なし)
400LLM_GENERATION_FAILED要約の生成に失敗した、または空の結果が返った
402INSUFFICIENT_BALANCE要約のコストを事前に確保できなかった
403FEATURE_DISABLEDアカウントでYouTube機能がオフになっている

機能のオン・オフ

YouTube要約APIは、パートナーアカウント単位とリクエスト単位でオプトインする方式です。アカウント全体の設定はコンソールの「機能設定」で管理します。リクエスト単位では、チャットはトップレベルの youtube:true、リーディングは tools: { "youtube": true } で有効にします。

ドキュメント処理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 は、ファイルが自動で呼び出された場合にのみ含まれます(空の場合は省略)。

料金と課金

機能のオン・オフ

ドキュメント処理はパートナーアカウント単位で有効・無効を切り替えられます。コンソールの「機能設定」で管理し、オフの場合はすべてのファイルリクエストが403を返します。

分析ステータスとチャンク

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 分析失敗(理由はレスポンスに含まれません — 再度アップロードしてください)

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:

HTTPコード発生条件
400FILE_NOT_PROVIDEDアップロード — file パートがない
400INVALID_FILE_TYPEアップロード — 非対応の形式
400FILE_TOO_LARGEアップロード — 10MB超(コードなしの413になる場合もあります)
400END_USER_REQUIREDアップロード — analyze=true なのに endUserId がない
400(なし)詳細 / 削除 — :id がUUIDでない
402INSUFFICIENT_BALANCEアップロード — 分析コストを事前に確保できなかった
403FEATURE_DISABLEDアカウントでドキュメント処理がオフになっている(4つのルートすべて)
404FILE_NOT_FOUND詳細 / 削除 — ファイルが存在しない、または別のアカウントのもの
422EXTRACTION_FAILEDアップロード — ドキュメントからテキストを抽出できなかった

感情分析(Emotion)

Chat APIの要約サイクルに乗せて、ユーザーとAIの感情状態を分析します。別途LLMを呼び出すことはなく、要約プロンプトに感情ブロックを追加するだけなので、追加料金はかかりません。ridm/* モデルでのみ対応しています。

概要

有効になる条件:

  1. グローバル:partner_emotion_enabled ✓
  2. パートナー:コンソールの機能設定で「感情分析」がオンになっている
  3. リクエスト:emotion: true が指定されている
  4. モデル:ridm/* モデルのみ

要約の間隔(summaryEvery)

感情分析は要約サイクルごとに自動で実行されます。サイクルの間隔は summaryEvery パラメータで設定します(デフォルト:5、範囲:1–20)。

リクエストパラメータ

パラメータ 型 必須 説明
emotion boolean 感情分析を有効にする(ridm/* モデルのみ、デフォルト:false)
summaryEvery number 整数 1–20(デフォルト 5)。要約と感情の更新間隔(ターン数)

リクエスト例

{
  "model": "ridm/gpt-5.6-terra",
  "user": "user_123",
  "messages": [
    { "role": "user", "content": "Today was a rough day..." }
  ],
  "emotion": true,
  "summaryEvery": 3
}

レスポンスフィールド

フィールドのパス 型 説明
emotion object|null 感情状態(最初のサイクルの前、または emotion=false の場合は null/省略)
emotion.user object ユーザーの感情
emotion.user.type10 string|null 10分類の感情ラベル(joyful|calm|curious|concerned|excited|thoughtful|neutral|sad|angry|surprised|null)
emotion.user.tone string|null トーン(自由形式の文字列 — 固定リストではありません。例:"warm")または null
emotion.user.distribution6 object 6分類の分布 {joy, sadness, anger, fear, disgust, surprise}、合計 = 1000 または 0
emotion.assistant object AIの感情
emotion.assistant.distribution6 object 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)

ストリーミングのレスポンス例(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]

コスト

注意事項

四柱推命画像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
  }
}

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:

HTTPコード発生条件
402INSUFFICIENT_BALANCE残高が画像1枚の料金に満たない
504IMAGE_UPSTREAM_TIMEOUT80秒以内に画像を受け取れなかった(課金なし)

画像生成API(モデル再販)

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

GPT-ImageとNano Bananaのモデルを、1つのキーでOpenAI Images APIと同じ形式で呼び出せます。モデル・解像度・品質ごとに1枚あたりの固定料金があり、表の金額がそのまま差し引かれます(生成枚数 × 1枚あたりの料金)。プロンプトの入力トークンのコストは1枚あたりの料金に含まれ、別途加算されません。

リクエストパラメータ

パラメータ型必須説明
modelstringOopenai/gpt-image-2, openai/gpt-image-1-mini, google/nano-banana-pro, google/nano-banana, fal/nano-banana-pro, fal/nano-banana
promptstringO生成する画像の説明(最大1,000文字)。超えた場合 → 422 PROMPT_TOO_LONG(残高の確保の後にチェックされるため、残高不足の場合は402が先に返ります)。空文字列 → 400 EMPTY_PROMPT
sizestringGPT-Image:1024x1024(デフォルト)・1024x1536(縦長)・1536x1024(横長)・auto(モデルが選択 — その品質で最も高いサイズの料金で課金)。旧形式の値 256x256 と 512x512 は1024x1024として、1792x1024 は1536x1024として、1024x1792 は1024x1536として生成・課金されます。Nano Bananaでは比率としてのみ使われます — aspect_ratio を推奨します。
qualitystringGPT-Imageのみ:low・medium(デフォルト)・high。旧形式の値 standard=medium、hd=high も引き続き使えます。Nano Bananaにlow/medium/highを送ると400を返します。
aspect_ratiostringNano Bananaのみ:21:9・16:9・3:2・4:3・5:4・1:1(デフォルト)・4:5・3:4・2:3・9:16。比率は料金に影響しません。size より優先されます。
resolutionstringNano Bananaのみ:Nano Bananaは 1K のみ、Nano Banana Proは 1K(デフォルト)・2K・4K に対応します。Kは大文字のみです。
nnumber画像の枚数、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": "..."
}

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)のほかに、このAPIが返すコード:

HTTPコード発生条件
400MODEL_NOT_FOUNDモデルが料金表にない
400INVALID_MODELopenai/、google/、fal/ 以外のプレフィックス
400INVALID_PARAMETERモデルが受け付けないオプション(GPT-Imageでの aspect_ratio や resolution、Nano Bananaでの quality、非対応の解像度)
400EMPTY_PROMPTプロンプトが空白のみ
400INVALID_PROMPTアップストリームのモデルがプロンプトを拒否した
400UPSTREAM_ERRORアップストリームのエラー、または画像0枚(課金なし)
HTTP 400、本文の status 429RATE_LIMITEDアップストリームのレート制限 — 少し待ってから再度お試しください
402INSUFFICIENT_BALANCE1枚あたりの料金 × n が残高を超えている
422PROMPT_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 の後に再度ポーリング
succeededresult = 同期呼び出しで返るはずだった200レスポンスそのもの(data、costWon、requestId)
failederror = 同期呼び出しで返るはずだったエラー本文そのもの(statusCode、code、message) — 課金なし
HTTPコード発生条件
202—Prefer: respond-async のリクエストが60秒以内に終わらなかった — 上記のジョブIDでポーリング
404IMAGE_JOB_NOT_FOUND未知・期限切れ、または他のパートナーのジョブID
429IMAGE_JOB_POLL_RATE_LIMITED同じAPIキーで2秒以内に再度ポーリングした — Retry-After 秒待ってください
error.statusCode 504IMAGE_UPSTREAM_TIMEOUT240秒以内に画像を受け取れなかった(課金なし)
error.statusCode 413IMAGE_JOB_RESULT_TOO_LARGE結果が16MBを超えている(課金なし)
error.statusCode 503IMAGE_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" になります。補正結果の形は、下の「注意事項」にある旧暦入力の例を参照してください。

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503など)に加えて、このAPIは次を返します:

HTTPコード発生条件
400INVALID_LUNAR_DATE · INVALID_LOCATION存在しない旧暦日付/緯度・経度の片方だけを送った(課金なし)
402(なし)残高が呼び出し料金より少ない — このAPIには呼び出し前の残高チェックがないため、402はコードなしで返ります

生涯四柱API

POST /api/v1/partners/v1/lifetime

生年月日と出生時刻から命式を計算し、その命式にあてはまる部分(日柱、日干×月支、日干×強弱、日干×用神、過不足のある五行を最大3つ、最も強い通変星のグループ)の解釈の段落を、性格・財運・仕事・恋愛・健康・人間関係・アドバイスの7つのテーマにまとめて返します。段落はHRUMの四柱推命理論で書かれており、同じ入力からは常に同じ結果が返ります。命式は万歳暦APIとまったく同じ方法で決まります。

7つのテーマすべて
1つのテーマ(topic)
西洋占星術と紫微斗数のレイヤー(layers)

リクエストパラメータ

パラメータ型必須説明
year · month · daynumberO出生年(1900-2100)・月・日(デフォルトは新暦。calendar: "lunar" で旧暦)
hour · minutenumber出生時刻。hour を省略すると、万歳暦APIと同じ出生時刻不明の規則(年・月・日の三柱)で計算します
timezonestringOタイムゾーン(例:Asia/Seoul)。認識できない名前はデフォルトのゾーンで計算し、レスポンスに警告(UNKNOWN_TIMEZONE)が付きます
genderstringO"male" または "female"
topicstring1つのテーマだけを取得する場合:personality、wealth、career、love、health、relationships、advice。省略すると7つのテーマすべて
langstringko(デフォルト)・en・ja・th
layersstring[]追加の解釈レイヤー:"astro"(西洋占星術 — 太陽・月・アセンダントのサイン)・"ziwei"(紫微斗数 — 命宮の主星+各テーマの宮の主星)。各テーマの四柱推命の段落の後に、西洋占星術、紫微斗数の順で追加されます。省略するか [] の場合、レスポンスは今とまったく同じです
calendar · isLeapMonthstring · boolean"lunar" の場合、year・month・day を旧暦の日付として読み、新暦に変換して計算します(デフォルトは "solar")。isLeapMonth: true は閏月を意味し、その年にその閏月がない場合は 400 INVALID_LUNAR_DATE(2026-10-12以降)。旧暦のリクエストでは、レスポンスに lunarInput が入ります(万歳暦APIと同じ形式)
birthLatitude · birthLongitudenumber出生地の座標(両方送ってください)。四柱推命の段落と layers は同じ真太陽時の補正を使います。標準子午線は timezone の標準時(夏時間を除く)から取ります。アセンダントには出生時刻と座標の両方が必要です
countrystring出生国の2文字の国コード。座標なしで KR・JP・TH を送ると、その国の代表経度で補正します(他の国は補正なし)。layers もこの国を使います(省略時は lang から推定)
zaSiRulestring子の刻(23:00以降)の日柱:"traditional"(デフォルト、翌日の日柱)・"yajaSi"(夜子時:当日の日柱。出生地補正後、23時台の時柱の天干は翌日の日干を基準にします。2026-10-20以降)。四柱推命の段落にだけ使います(紫微斗数は常に23:00で翌日に切り替わります)
birthTimePrecisionstringexact・approximate・estimated・unknown。出生地補正は exact のときだけ適用されます。省略した場合、座標または country を送っていれば exact として扱います

リクエスト例

{
  "year": 1990, "month": 9, "day": 4, "hour": 14, "minute": 30,
  "timezone": "Asia/Seoul", "gender": "male",
  "topic": "career", "lang": "ko"
}

レスポンス例

{
  "success": true,
  "data": {
    "topics": [
      {
        "topic": "career",
        "paragraphs": [
          { "component": "ilju", "key": "임신", "text": "..." },
          { "component": "ilgan_wolji", "key": "임_신", "text": "..." },
          { "component": "ilgan_strength", "key": "임_신강", "text": "..." },
          { "component": "ilgan_yongshin", "key": "임_화", "text": "..." },
          { "component": "ohaeng_state", "key": "목_lack", "text": "..." },
          { "component": "ohaeng_state", "key": "토_lack", "text": "..." },
          { "component": "ohaeng_state", "key": "수_lack", "text": "..." },
          { "component": "top_sipsin", "key": "인성", "text": "..." }
        ]
      }
    ],
    "lang": "ko",
    "fallbackLanguage": null,
    "engine": { "version": 1, "styleVersion": "v1" }
  }
}
  • topics は常に上の7テーマの順に並びます。テーマ内の段落は部分の順(日柱 → 日干×月支 → 強弱 → 用神 → 五行の状態 → 通変星のグループ)に並びます。
  • key は韓国語の判定値です(言語に依存しません)。ohaeng_state の段落は命式によって0〜3個です。
  • 言語:リクエストした言語の段落がまだない場合、その段落だけが韓国語で返り、fallbackLanguage: "ko" が設定されます。
  • 時刻の補正:座標も country もない場合、入力した時刻をそのまま使います(万歳暦APIと同じ)。INTAアプリ(韓国語、時刻を直接入力)と同じ段落を得るには country: "KR" を送ってください。海外で生まれた人の場合、timezone だけでは時刻は補正されません — 座標もあわせて送ってください。
  • 2026-10-11の変更:座標を送った場合、四柱推命の段落も真太陽時で補正するようになりました(以前は layers だけが使っていました)。これにより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コード発生条件
404lifetime_not_enabledアカウントでこの機能が有効になっていない
400INVALID_LUNAR_DATE · INVALID_LOCATION存在しない旧暦日付/緯度・経度の片方だけを送った
402INSUFFICIENT_BALANCEリクエストしたレイヤーを含む金額で事前に確認したときに残高不足
503lifetime_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 · daynumberO出生年(1900-2100)・月・日
hournumberO出生時(0-23)。出生時がないと紫微斗数の命盤は作れません — 省略すると 400 birth_time_required になります
minutenumber出生分(0-59)、省略時は0
genderstringO"male" または "female"(大限の向きを決めます)
calendarstringsolar(デフォルト)または lunar
isLeapMonthboolean旧暦の閏月なら true。新暦の入力では無視されます。その年にその閏月がない場合は平月を使い、chart.lunarDate.isLeapMonth は false で返ります
birthTimePrecisionstringexact(真太陽時で補正)または approximate(補正なし+notes.approximateTimeNote)。省略時は補正なし
birthLatitude · birthLongitudenumber出生地の座標(exact の補正用)
countryCodestring出生国、ISOの2文字コード、大文字のみ(例:KR — kr は400を返します)。座標を送らないときに代表経度で補正するのに使います
birthTimezoneOffsetnumber出生時刻のUTCオフセット(分、540 = KST)
referenceDatestring大限・流年の基準日、YYYY-MM-DD(デフォルト:今日、韓国時間)
langstringko(デフォルト)・en・ja・th
timezonestring万歳暦APIとの互換用(計算には使わないため、名前を認識できなくても警告は付きません)
readingsbooleantrue の場合、レスポンスに 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(アカウントで機能が有効になっていない)・404 ziwei_readings_not_enabled(解釈の段落が有効になっていない)・503 ziwei_readings_unavailable(解釈の段落を読み込めなかった)。

エラーコード

共通エラー(401、400 本文の検証、402、429、503など)に加えて、このAPIは次を返します:

HTTPコード発生条件
404ziwei_not_enabledアカウントでこの機能が有効になっていない
404ziwei_readings_not_enabledreadings: true なのに解釈の段落が有効になっていない
400invalid_birth_date存在しない新暦の日付、または範囲外の旧暦の日・閏月
400birth_time_requiredhour がない — 上の例のように partial が一緒に返ります
400reference_date_before_birthreferenceDate が生年月日より前
402INSUFFICIENT_BALANCE残高不足
503ziwei_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/回です(アカウントで有効な場合のみ。それ以外は404 identity_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コード発生条件
404identity_not_enabledアカウントで有効になっていない
400INVALID_LUNAR_DATE · INVALID_LOCATION存在しない旧暦日付 / 緯度と経度の片方だけを送った
402INSUFFICIENT_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の整数でない、未知のキー
400INVALID_LUNAR_DATE · INVALID_LOCATION存在しない旧暦日付 / 緯度と経度の片方だけを送った
402INSUFFICIENT_BALANCE残高不足
404saju_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が付きます。さらに以下を受け付けます:

パラメータ型必須説明
datestring見る日付、YYYY-MM-DD(1900-2100)。省略すると韓国時間の今日
temperatureCnumber現在の気温(℃、−40~50)。送るとレスポンスにfashion(朝・昼・夜のコーデ)が加わります。省略するとfashionはありません(推定はしません)
weatherstring天気:clear · cloudy · rain · snow · storm
humiditynumber相対湿度(%、0~100)。fashion.mood(時間帯ごとの1行の天気コメント)はtemperatureC·weather·humidityの3つをすべて送ったときだけ加わります
mbtiBehaviorbooleantrueなら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コード発生条件
404today_not_enabledアカウントで機能が有効になっていない
400INVALID_LUNAR_DATE · INVALID_LOCATION存在しない旧暦日付 / 緯度と経度の片方だけを送った
402INSUFFICIENT_BALANCE残高不足

夢占いAPI

POST /api/v1/partners/v1/dream

エンドユーザーが語った夢から象徴語(例:海、魚)を見つけ、目立つ順に返します。語はHRUM独自の夢の象徴語集(日常的な名詞約1,000語と、その類義語・活用形・口語形)から取られます。語集にあるのは語だけで、夢の意味や吉凶の判定は含まれません。返される語はすべて、語そのもの、または類義語・活用形として実際に夢のテキストに現れています。

リクエストパラメータ

パラメータ型必須説明
dreamstring✓夢の内容(1,000文字まで)
feelingstring夢の感じ(300文字まで、例:「무섭고 답답했어요」—「怖くて息苦しかった」)。夢のテキストと合わせてタグを抽出します(合わせたテキストの1,000文字までを使用)
langstringレスポンスの言語。現在はkoのみ対応です(辞書が韓国語のみのため)。それ以外の値は400
includeNegativeboolean 古典資料のうち、凶の判定の記録(死、病気、喪失など)を含めるかどうか。既定はfalse。古典資料が使えるようになるまでは無視されます

リクエスト例

{
  "dream": "바다에서 커다란 물고기를 두 손으로 잡는 꿈을 꿨어요"
}

レスポンス例

{
  "success": true,
  "data": {
    "lang": "ko",
    "mode": "glossary",
    "items": [
      { "keywords": ["바다"], "score": 1 },
      { "keywords": ["물고기"], "score": 0.979 },
      { "keywords": ["손"], "score": 0.749 }
    ]
  }
}
  • itemsは最大40件です。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コード発生条件
404dream_not_enabledアカウントで機能が有効になっていない
402INSUFFICIENT_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, modelVersionstring✓座標を出したモデル。許可リスト外:400 MEASURE_MODEL_UNSUPPORTED / MEASURE_MODEL_VERSION_MISMATCH。現在:face_landmarker · float16/[email protected]
normalizationstring✓face-norm-1
landmarksnumber[][]✓ちょうど478個の[x, y]または[x, y, z](画像の幅・高さで割った値、−0.02~1.02)
imageWidth, imageHeightnumber✓ピクセル単位のサイズ
hairline[number, number]顔の中央の生え際の1点。サーバーは推定しません — ないと上停(顔の上部の区画)に関するキーはnullになります(理由hairline_missing)。額の上で髪が始まる位置をユーザーにタップしてもらうことをおすすめします(髪のセグメンテーションモデルは参考程度です)
qualityobjectyawDeg·pitchDeg·rollDeg·blendshapes(MediaPipeの係数名 → スコア)。送った場合のみ品質チェックを行います
includeNegativeboolean凶の判定の記録(polarity negative)を含めるかどうか。既定はfalse(夢占いと同じ名前・意味)

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

パラメータ型必須説明
modelName, modelVersionstring✓現在:hand_landmarker · float16/[email protected]
normalizationstring✓palm-norm-1
landmarksnumber[][]✓ちょうど21個
imageWidth, imageHeightnumber✓ピクセル単位のサイズ
handednessstring✓left | right — 被写体の実際の手(ユーザーに選んでもらってください)
mirroredboolean左右反転した写真(自撮りプレビュー)ならtrue
creasesobject[]手相線のポリライン(64本まで、1本あたり2~512点)。フィールド:points(✓)、label(life·head·heart·fate·sun·mercury·simian·unknown)、kind(segment | branch)、autoLabel。ないと線に関するキーはnullになります(creases_missing)
autoLabelboolean名前のない線すべてに、サーバー共通のヒューリスティックで名前を付けます。1本だけに使う場合はその項目にautoLabelを指定します。自分で指定したlabelが常に優先されます
includeNegativeboolean顔と同じ。既定は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コード意味
400MEASURE_MODEL_UNSUPPORTEDmodelNameが許可リストにない
400MEASURE_MODEL_VERSION_MISMATCHmodelVersionが許可リストにない(現在はfloat16/[email protected]のみ)
400MEASURE_NORMALIZATION_MISMATCHnormalizationがface-norm-1 / palm-norm-1でない
400MEASURE_LANDMARK_COUNT点の数が顔で478 / 手で21でない
400MEASURE_LANDMARK_SHAPE · MEASURE_COORD_NAN · MEASURE_COORD_RANGE · MEASURE_IMAGE_SIZE · MEASURE_DEGENERATE点の形式、数値、範囲(−0.02~1.02)、画像サイズのエラー
400MEASURE_HANDEDNESS · MEASURE_CREASE_LIMIT · MEASURE_CREASE_SHAPE · MEASURE_CREASE_LABEL手または手相線の入力エラー
400MEASURE_QUALITY_POSE · MEASURE_QUALITY_FACE_SIZE頭が10°を超えて回転 · 顔が小さすぎる — 撮り直してください
400(検証エラー)ドキュメントにないフィールドを送った — 許可されたフィールドだけを送ってください
402INSUFFICIENT_BALANCEクレジット残高不足
404face_measure_not_enabled · palm_measure_not_enabled機能がまだ公開されていない

エラーレスポンスはすべて課金されません。

個人データ

  • 写真は受け取りません。写真はユーザーの端末で座標に変換され、APIに届くのは座標だけです。
  • 座標は保存しません。座標は顔や手の形状のため、サーバーはリクエストの処理中にメモリー上でだけ使い、ログ、データベース、エラーメッセージには残しません。利用ログに記録するのはエンドポイント、ステータス、金額だけです。
  • エンドユーザーの同意はパートナー側で取得してください。
  • 参考コードで使う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

パラメータ型必須説明
imageobjectどちらか一方{ data, mimeType } — dataは写真のバイト列のbase64(デコード後8MBまで)、mimeTypeはimage/jpeg · image/png · image/webp。形式はバイト列からも再確認されます(異なれば400)
landmarksobjectどちらか一方顔計測のリクエスト本文そのまま(modelName · modelVersion · normalization · landmarks 478点 · imageWidth · imageHeight · hairline · quality · includeNegative)
consentobject写真なら✓写真の処理への同意 — 下記の同意オブジェクトをご覧ください
llmboolean送る必要はありません — AIの解釈は常に含まれます。falseを送ると400 USE_FACE_MEASURE(AIなしの計測は顔計測)
langstringko · en · ja · thを受け付けますが、解釈の文章は現在韓国語のみです(レスポンスのlang = "ko")
endUserIdstringパートナーが使うエンドユーザー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

パラメータ型必須説明
imageobject✓手のひら側の写真1枚。形式とサイズの制限は人相占いと同じ
consentobject✓同意オブジェクト
creasesobject[]ユーザーが写真の上でなぞった手相線(16本まで)。フィールド:line(life · head · heart · fate · sun · mercury · simian · unknown)、points(2~256個の[x, y]、写真の左上からの0~1)。線の位置を特定するときに優先して使われます
langstring人相占いと同じ(解釈の文章は現在韓国語のみ)
endUserIdstring人相占いと同じ

リクエスト例(手のひら、なぞった線あり)

{
  "image": { "data": "/9j/4AAQSkZJRgABAQ…(base64)", "mimeType": "image/jpeg" },
  "consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" },
  "creases": [
    { "line": "life", "points": [[0.42, 0.38], [0.36, 0.52], [0.34, 0.71]] },
    { "line": "heart", "points": [[0.78, 0.33], [0.6, 0.31], [0.47, 0.34]] }
  ]
}

例:"consent": { "photo": true, "version": "photo-consent-2026-10", "subject": "end_user" }

  • photo:必ずtrue — ユーザーが写真の処理に同意したことを表します。
  • version:パートナーが表示した同意文のバージョン(1~40文字)。
  • subject:end_user(ユーザー本人の写真)· third_party(他人の写真 — パートナーはその人の同意も取得する必要があります)。
  • 値がない、または無効な場合は400 CONSENT_REQUIREDになります。利用ログにはversionとsubjectだけが記録されます。

写真の処理

  • 写真はリクエストの処理中にメモリー上でのみ使います。ディスク、データベース、ログ、ファイルストレージには残さず、顔や手の特徴量(テンプレート、埋め込み)も作成・保存しません。誰であるかの識別や、他の写真との照合は行いません。
  • 外部モデルに送る前に、EXIF(位置情報や端末情報を含む)、XMP、ICCなどのメタデータを削除し、長辺を最大1600pxにしてJPEGで再エンコードします。WebPはメタデータだけを削除してそのまま送るため、長辺1600px以下のWebPのみ受け付けます(それより大きいと413 — 縮小するか、JPEG/PNGで送ってください)。
  • 写真1枚につき外部モデルを2回呼び出します。まず写真を分類し(顔または手のひらか、1人か、未成年に見えるか、画質)、通過した場合のみ解釈を書きます。どちらの呼び出しもstore: falseを使います。
  • 未成年(18歳未満)に見える写真は読み解きません。複数の人や2つ以上の手が写った写真、顔や手のひらではない写真も同様です(400 IMAGE_NOT_ALLOWED)。手の甲の写真は400 PALM_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コード意味
400READING_INPUT_ONE_OF顔:imageとlandmarksのどちらか一方だけになっていない
400IMAGE_REQUIRED手のひら:imageがない
400CONSENT_REQUIRED写真を送ったがconsentがない、または無効
400IMAGE_INVALID · IMAGE_FORMAT_UNSUPPORTED読めない写真 · mimeTypeが実際の形式と異なる · JPEG、PNG、WebPではない(アニメーションWebPを含む)
413IMAGE_TOO_LARGE8MBを超える写真 · 8192pxまたは1680万画素を超える · WebPの長辺が1600pxを超える
400IMAGE_NOT_ALLOWED未成年に見える · 複数の顔 / 2つ以上の手 · 顔や手のひらの写真ではない
400FACE_NOT_DETECTED · PALM_NOT_DETECTED顔 / 手のひらが見つからない(手の甲の写真はPALM_NOT_DETECTED)
400USE_FACE_MEASURE顔のlandmarksでllm: false — AIなしの計測は顔計測API
400MEASURE_LOW_QUALITYぼやけている · 暗い · 隠れている · 小さすぎる · 傾いている — 理由はレスポンスのqualityにあります。ユーザーに撮り直してもらってください
400CREASE_INVALID手相線の点が2個未満、または0~1の範囲外の点がある
400MEASURE_*landmarksの入力エラー(顔計測と同じコード)
402INSUFFICIENT_BALANCE残高不足 — 外部モデルを呼び出す前に確認します
404face_reading_not_enabled · palm_reading_not_enabled機能がまだ公開されていない
409IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS同じX-Idempotency-Keyが別の本文で使われた · 同じキーの最初のリクエストがまだ処理中(下記の再試行と再送信をご覧ください)
429FILTERED_QUOTA_EXCEEDED今日除外された写真が1日の上限に達した — 下記の除外された写真の1日の上限をご覧ください
502READING_UNAVAILABLE解釈を作成できなかった(出力の途切れを含む) — もう一度お試しください
503IMAGE_BUSY写真の処理が混み合っている — しばらくしてからもう一度お試しください
504LLM_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.hangulstring✓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文字)。字義の五行はこの意味だけから判定します
birthobject{ year, month, day, hour?, minute?, gender?, timezone? }(新暦)。送ると四柱推命の用神を計算し、名前がその五行を補っているかを見ます。timezoneの既定はAsia/Seoul。生年月日は外部モデルに送りません
interpretboolean既定はtrue(姓名判断)。falseなら姓名計算のみ(AIなし)
echoNameboolean2026-10-31追加。既定はtrue(従来どおり)。falseにすると、名前の文字をレスポンスのどこにも書き戻しません — nameはnull、deterministic.syllablesのhangul·hanja·meaningはnullになり、代わりにposition(1から)が加わります。items内の文字への言及も「첫 글자(목(木))」(「1文字目(木(木))」)のように位置に切り替わり、姓名判断では名前そのものをAIに送りません(計算値と位置だけを送ります)
consentobject姓名判断なら✓{ "version": "name-consent-2026-10", "subject": "end_user" } — versionはパートナーが表示した同意文のバージョン(1~40文字)、subjectはend_user · third_party。値がない、または無効な場合は400 CONSENT_REQUIRED。利用ログにはversionとsubjectだけが記録されます。interpret: falseなら不要
langstringko · en · ja · thを受け付けますが、現在は韓国語でのみ答えます
endUserIdstringパートナーのエンドユーザー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コード意味
400NAME_INVALIDハングルの名前が2~6音節でない · hanja/strokes/meaningsの値の形式エラー
400NAME_HANJA_LENGTHhanjaの長さが音節数と異なる
400CONSENT_REQUIRED姓名判断でconsentがない、または値が無効
400(検証エラー)存在しない日付 · ドキュメントにないフィールド
402INSUFFICIENT_BALANCE残高不足
404naming_not_enabled機能がまだ公開されていない(姓名判断と姓名計算は別々)
409IDEMPOTENCY_KEY_REUSED · IDEMPOTENCY_IN_PROGRESS同じX-Idempotency-Keyが別の本文で使われた · 同じキーの最初のリクエストがまだ処理中(下記の再試行と再送信をご覧ください)
502READING_UNAVAILABLEAIの解釈を作成できなかった — 課金されません(計算だけを返す部分課金もありません)。もう一度お試しください
504LLM_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通りあります。

リクエストパラメータ

パラメータ型必須説明
countnumber△引く枚数、1~10(整数)。countとspreadはどちらか一方だけを送ります。両方送るか、どちらも送らないと400を返します
spreadstring△スプレッド。それぞれ枚数とポジション名が決まっています:single(今日の1枚、1枚)・past-present-future(過去・現在・未来、3枚)・choice(選択:現状・障害・結果、3枚)・celtic-condensed(簡略版ケルト十字、5枚)・future-prediction(未来予測、5枚)
reversedboolean逆位置を許可するか(デフォルトtrue)。falseにするとすべて正位置になります
seedstring再現性のための文字列(1~200文字)。同じseed+同じcount/spread+同じreversedなら、常に同じカードを引きます。指定しない場合は毎回ランダムです(暗号論的乱数)
questionstringエンドユーザーの質問(最大500文字)。解釈には使われず、レスポンスにそのまま返ります — 後段のLLMに渡すための便利フィールドです
langstringカード名・キーワード・意味・スプレッド名の言語:ko(デフォルト)・en・ja・th

リクエスト例

{
  "spread": "past-present-future",
  "question": "올해 하반기에 이직해도 될까요?",
  "seed": "user-1042:2026-10-10"
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/tarot \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"count": 1, "lang": "en", "reversed": false}'

レスポンス例(カード1枚分を抜粋)

{
  "success": true,
  "data": {
    "lang": "ko",
    "count": 3,
    "spread": { "type": "past-present-future", "name": "과거·현재·미래", "description": "시간 흐름을 따라가는 질문", "positions": ["과거", "현재", "미래"] },
    "reversedAllowed": true,
    "seed": "hrum-example-1",
    "cards": [
      {
        "position": 1,
        "positionLabel": "과거",
        "id": "wands_10",
        "name": "완드의 10",
        "nameEn": "Ten of Wands",
        "arcana": "wands",
        "reversed": true,
        "keywords": ["내려놓기", "위임", "해방"],
        "meaning": "무거운 짐을 마침내 내려놓거나 도움을 받기 시작하는 시기.",
        "imageUrl": "https://console.hrum.ai/tarot/cards/v2/wands_10.webp"
      }
    ],
    "cardBackUrl": "https://console.hrum.ai/tarot/cards/v2/back.webp",
    "question": "올해 하반기에 이직해도 될까요?",
    "costPoints": 20
  }
}

料金

ウェイトの原典テキスト kb

公開されると、レスポンスにkbが追加されます。引いたカードごとに、A. E. ウェイト『The Pictorial Key to the Tarot』(1910年、パブリックドメイン)の原文から、そのカードの正位置・逆位置の意味を、ルールID(R-TAROT-*)と原文の引用付きで返します。上のmeaning・keywordsはそのままで、kbだけが追加され、価格も同じです。

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

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
404tarot_not_enabledアカウントでこの機能が有効になっていない
404tarot_kb_not_enabledmethodを送ったが、原典テキスト機能がまだ公開されていない
402INSUFFICIENT_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(課金なし)。

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
404natal_readings_not_enabledreadings: trueだが、リーディング文章が有効になっていない
503natal_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(正午基準)です。

パラメータ型必須説明
houseSystemsstring[]placidus・whole_sign・equal・porphyryから任意。省略すると["placidus"]。極圏内の出生地(緯度が約66.56°を超える、angles.polar)では、プラシーダスの代わりにポルフィリーで計算し、結果に"fallbackFrom": "placidus"が付きます(プラシーダスを明示的にリクエストした場合も同じです)
minorAspectsbooleanセミセクスタイル(30°)・セミスクエア(45°)・セスキコードレート(135°)・クインカンクス(150°)を含めます(ネイタルとシナストリー)。デフォルトfalse — メジャーアスペクト5種のみ
orbsstringネイタルとシナストリーのオーブ表:leo1928(デフォルト — コンジャンクション/オポジションは太陽–月12°、太陽・月–惑星10°、惑星–惑星8°、スクエア/トライン8°、セクスタイル7°、セミスクエア/セスキコードレート4°、セミセクスタイル/クインカンクス2°)・heindel1919(メジャーは一律6°、保守的)
nodestringルールキーのNn(ノースノード)とSn(サウスノード=ノースノード+180°)がどちらのノードに従うか:mean(デフォルト、平均ノード)・true(真ノード)。featuresのnode_sign Nn_…・Sn_…と、ノードのコンジャンクションキー(Mo_Nn_cj・Nn_Asc_cjなど)に適用されます。MNn_…・TNn_…のキーはこの値に関係なく両方返ります
langstringsignName(サイン名)の言語 — ko(デフォルト)・en・ja・th
timingobject送るとトランジット+セカンダリー・プログレッションを計算し、レスポンスのtimingに入れます。下の表を参照
partnerobject相手の出生情報(lang以外は上と同じフィールド)。送ると、2人の間のアスペクトとサインの関係がレスポンスのsynastryに入ります。相手の出生時刻と座標(birthLatitude・birthLongitude)があれば、相手のアセンダント(Asc)とMC(ミッドヘブン)も計算し、クロスアスペクトに含めます

timingブロックの中身:

パラメータ型必須説明
orbDegreesnumberOトランジット→ネイタル、プログレス→ネイタルのアスペクトのオーブ(度)、0.5~10。すべての天体の組み合わせに同じ値を使います(メジャーアスペクト5種のみ)
atstring見る時点。YYYY-MM-DD(=その日のUTC 00:00)またはオフセット付きの日時(2026-10-11T09:00:00+09:00、...Z)。オフセットのない日時は400を返します。省略すると現在
progressionsbooleanセカンダリー・プログレッションを計算するか(デフォルトtrue)
yearLengthstring経過時間を「年齢(年)」に換算するときの1年の長さ:tropical(365.24219日、デフォルト)・julian(365.25日)

リクエスト例1 — デフォルト(ネイタルのみ)

{
  "birthDate": "1990-05-15",
  "birthTime": "14:30",
  "birthTimePrecision": "exact",
  "birthLatitude": 37.5665,
  "birthLongitude": 126.978,
  "houseSystems": ["placidus", "whole_sign"]
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "birthLatitude": 37.5665, "birthLongitude": 126.978, "minorAspects": true, "lang": "en"}'

レスポンス例1(抜粋、実際のエンジン出力)

{
  "success": true,
  "data": {
    "natal": {
      "utc": "1990-05-15T05:30:00.000Z",
      "timePrecision": "exact",
      "timeKnown": true,
      "zodiac": "tropical",
      "lang": "ko",
      "bodies": [
        { "id": "Sun", "longitude": 54.1347, "sign": "Taurus", "signKey": "tau", "signName": "황소자리", "degreeInSign": 24.1347, "speed": 0.9643, "retrograde": false, "dignities": [], "house": { "placidus": 9, "whole_sign": 9 } },
        { "id": "Moon", "longitude": 293.8244, "sign": "Capricorn", "signKey": "cap", "signName": "염소자리", "degreeInSign": 23.8244, "speed": 12.2943, "retrograde": false, "dignities": ["det"], "house": { "placidus": 4, "whole_sign": 5 } },
        ...
      ],
      "nodes": [
        { "id": "MeanNode", "longitude": 311.3535, "sign": "Aquarius", "signName": "물병자리", "speed": -0.0529,
          "south": { "longitude": 131.3535, "sign": "Leo", "signName": "사자자리", ... } },
        { "id": "TrueNode", ... }
      ],
      "angles": { "asc": 173.5996, "mc": 82.8067, "dsc": 353.5996, "ic": 262.8067,
        "ascSign": { "sign": "Virgo", "signName": "처녀자리", ... }, "mcSign": { ... }, "dscSign": { ... }, "icSign": { ... }, "polar": false },
      "anglesOmitted": null,
      "houseSystems": ["placidus", "whole_sign"],
      "houses": {
        "placidus": { "cusps": [173.5996, 199.6989, 229.8749, ...], "bodies": { "Sun": 9, "Moon": 4, "Jupiter": 10, ... } },
        "whole_sign": { "cusps": [150, 180, 210, ...], "bodies": { "Sun": 9, "Moon": 5, ... } }
      },
      "housesExcluded": [],
      "orbs": "leo1928",
      "minorAspects": false,
      "aspects": [
        { "a": "Jupiter", "b": "Uranus", "type": "opposition", "code": "op", "key": "Ju_Ur_op", "separation": 179.6986, "orb": 0.3014, "orbLimit": 8, "strength": "exact", "applying": false, "outOfSign": false },
        { "a": "Sun", "b": "Moon", "type": "trine", "code": "tr", "key": "Su_Mo_tr", "orb": 0.3104, "orbLimit": 8, "strength": "exact", "applying": true, "outOfSign": false },
        ...
      ],
      "dignities": { "Sun": [], "Moon": ["det"], "Mercury": [], "Venus": ["det"], "Mars": [], "Jupiter": ["exa"], "Saturn": ["dom"] },
      "moonSignUncertain": false,
      "features": [
        { "type": "planet_sign", "key": "Su_tau" },
        { "type": "dignity", "key": "Mo_det" },
        { "type": "planet_retrograde", "key": "Me_rx" },
        { "type": "planet_house", "key": "Su_h9", "system": "placidus" },
        { "type": "aspect", "key": "Su_Mo_tr", "strength": "exact", "applying": true, "orb": 0.31 },
        { "type": "meta", "key": "time_known" },
        ...
      ]
    },
    "readings": {
      "dignities": [
        { "key": "Mo_det", "text": "달이 염소자리에서 손상 자리에 있으면 감정을 바로 내보이기보다 책임과 일의 질서 속에서 조심스럽게 다루는 경향이 있어요. ...", "lang": "ko" },
        { "key": "Ve_det", ... }, { "key": "Ju_exa", ... }, { "key": "Sa_dom", ... }
      ],
      "aspects": [
        { "key": "Su_Mo_tr", "text": "태양과 달의 트라인은 의지와 정서가 같은 곳을 바라봐, 스스로 길을 내며 생활 전반을 고르게 꾸려 가는 힘이 실려요. ...", "lang": "ko", "deviation": 0.31 },
        { "key": "Su_Sa_tr", ... }, { "key": "Mo_Sa_cj", ... }, ...
      ],
      "lang": "ko"
    },
    "readingsUnavailable": false,
    "costPoints": 50
  }
}

timing・partnerを送らない場合、レスポンスにtiming・synastryキーは一切ありません。

リクエスト例2 — timing付き(トランジット+セカンダリー・プログレッション)

{
  "birthDate": "1990-05-15",
  "birthTime": "14:30",
  "birthTimePrecision": "exact",
  "birthLatitude": 37.5665,
  "birthLongitude": 126.978,
  "houseSystems": ["whole_sign"],
  "timing": { "at": "2026-10-11T09:00:00+09:00", "orbDegrees": 3, "yearLength": "tropical" }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"birthDate": "1990-05-15", "timing": {"orbDegrees": 2, "progressions": false}}'

レスポンス例2(抜粋。natalは例1と同じ形)

{
  "success": true,
  "data": {
    "natal": { ... },
    "timing": {
      "at": "2026-10-11T00:00:00.000Z",
      "orbDegrees": 3,
      "natalPoints": ["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "Asc", "MC"],
      "transits": {
        "bodies": [ { "id": "Sun", "longitude": 197.6966, "sign": "Libra", "signName": "천칭자리", "speed": 0.9889, "retrograde": false, ... }, ... ],
        "aspects": [
          { "a": "Mars", "b": "Mercury", "type": "square", "key": "tMa_nMe_sq", "orb": 0.6358, "orbLimit": 3, "strength": "exact", "applying": true, "outOfSign": false },
          ...
        ]
      },
      "progressions": {
        "yearLength": "tropical",
        "yearLengthDays": 365.24219,
        "ageYears": 36.4081,
        "instant": "1990-06-20T15:17:39.048Z",
        "bodies": [ { "id": "Sun", "longitude": 89.0352, "sign": "Gemini", "signName": "쌍둥이자리", ... }, ... ],
        "aspects": [
          { "a": "Uranus", "b": "Mercury", "type": "trine", "key": "pUr_nMe_tr", "orb": 0.0862, "orbLimit": 3, "strength": "exact", "applying": false, "outOfSign": false },
          ...
        ]
      },
      "features": [
        { "type": "transit", "key": "tMa_nMe_sq", "strength": "exact", "applying": true, "orb": 0.64 },
        { "type": "progressed", "key": "pUr_nMe_tr", "strength": "exact", "applying": false, "orb": 0.09 },
        ...
      ]
    },
    "readings": { ... }, "readingsUnavailable": false,
    "costPoints": 50
  }
}

リクエスト例3 — partner付き(シナストリー)

{
  "birthDate": "1990-05-15",
  "birthTime": "14:30",
  "birthTimePrecision": "exact",
  "birthLatitude": 37.5665,
  "birthLongitude": 126.978,
  "houseSystems": ["whole_sign"],
  "partner": { "birthDate": "1992-11-03", "birthTime": "08:10", "birthTimePrecision": "exact", "birthLatitude": 35.1796, "birthLongitude": 129.0756 }
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/astrology \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"birthDate": "1990-05-15", "birthTime": "14:30", "birthTimePrecision": "exact", "partner": {"birthDate": "1992-11-03"}}'

レスポンス例3(抜粋。natalは例1と同じ形)

{
  "success": true,
  "data": {
    "natal": { ... },
    "synastry": {
      "partner": {
        "utc": "1992-11-02T23:10:00.000Z",
        "timePrecision": "exact",
        "timeKnown": true,
        "moonSignUncertain": false,
        "bodies": [ { "id": "Sun", "longitude": 220.7903, "sign": "Scorpio", "signName": "전갈자리", "speed": 1.0016, "retrograde": false, "dignities": [], ... }, ... ],
        "angles": { "asc": 252.31, "mc": 175.86, "ascSign": { "sign": "Sagittarius", "signName": "사수자리", ... }, "mcSign": { "sign": "Virgo", "signName": "처녀자리", ... } },
        "anglesOmitted": null
      },
      "orbs": "leo1928",
      "minorAspects": false,
      "aspects": [
        { "a": "Moon", "b": "Mars", "type": "opposition", "code": "op", "key": "aMo_bMa_op", "orb": 0.2993, "orbLimit": 10, "strength": "exact", "applying": null, "outOfSign": false },
        { "a": "Neptune", "b": "Uranus", "type": "conjunction", "code": "cj", "key": "aNe_bUr_cj", "orb": 0.3898, "orbLimit": 8, "strength": "exact", "applying": null, "outOfSign": false },
        ...
      ],
      "features": [
        { "type": "syn_aspect", "key": "aMo_bMa_op", "strength": "exact", "orb": 0.3 },
        { "type": "syn_aspect", "key": "aNe_bUr_cj", "strength": "exact", "orb": 0.39 },
        { "type": "astro_syn", "key": "Su_Mo_se" },
        { "type": "syn_sign", "key": "aAsc_bAsc_es" },
        ...
      ]
    },
    "readings": { ... }, "readingsUnavailable": false,
    "costPoints": 50
  }
}

デフォルトと選ぶ必要がある値

提供していないもの

料金

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
404astrology_not_enabledアカウントでこの機能が有効になっていない
400at_before_birthtiming.atが出生時刻より前(プログレッションがオンの場合)
402(なし)残高が呼び出し価格より少ない — このAPIは呼び出し前の残高チェックがないため、コードなしの402が返ります

運勢フローAPI

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

パラメータ型必須説明
birthDatestringOYYYY-MM-DD(1900~2100)。指定したcalendarでの日付
birthTimestring | nullHH:mm。ない場合は時柱が不明 — 6文字で計算し、hourKnown: false
calendarstringOsolar・lunar(旧暦の日付は新暦に換算して計算)
isLeapMonthboolean旧暦の閏月(デフォルトfalse)
genderstring | nullmale・female。ない場合は大運の層がありません(daeun: []、daeunIndex: null)
timezonestringAsia/Seoulのみ受け付けます
birthLatitude · birthLongitudenumber出生地の座標(両方送る必要があります)。万歳暦APIと同じフィールドとルール — 経度を真太陽時の補正に使い、運勢フローは万歳暦が返すのと同じ補正済みの命式の上に描かれます。片方だけ送ると400 INVALID_LOCATIONを返します。送らない場合は万歳暦のデフォルト処理(現在は補正なし)が適用され、assumedLocationで示されます
countrystring出生国、2文字のコード。座標なしでKR・JP・THを送ると、その国の代表経度で補正します(万歳暦と同じ)
birthTimePrecisionstringexact・approximate・estimated・unknown。補正はexactの場合のみ適用されます(位置を送った場合のデフォルトはexact)。exact以外の値では真太陽時の補正はありません。韓国の夏時間期間の出生は、万歳暦と同じく1時間引いて標準時として読みます(2026-10-16)
rangeobjectO{ "fromYear", "toYear" }、年運の範囲(新暦の年、最大101年)。出生年~出生年+100を一度取得し、画面で切り出して使うことをおすすめします
monthsOfYearinteger | null月運の12スロットを計算する四柱推命上の年(その年の立春から翌年の立春の直前まで)。省略すると、現在(韓国時間)を含む四柱推命上の年 — 1月1日から立春の前までは前年です。nullにすると月運の層はありません(months: [])
langstringko・en・ja・th。レスポンスの値は言語に依存しないコード(干支の韓国語読み、五行、関係名)なので、現在はどの言語でも結果は同じです。一覧は有効な値 > 言語に依存しないコード値を参照してください。

リクエスト例

{
  "birthDate": "1990-05-15",
  "birthTime": "14:30",
  "calendar": "solar",
  "gender": "male",
  "timezone": "Asia/Seoul",
  "range": { "fromYear": 1990, "toYear": 2090 },
  "monthsOfYear": 2026
}
curl -X POST https://api.hrum.ai/api/v1/partners/v1/saju-flow \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: chart-123:flow:2026" \
  -d '{"birthDate": "1990-05-15", "birthTime": "14:30", "calendar": "solar", "gender": "male", "timezone": "Asia/Seoul", "range": {"fromYear": 1990, "toYear": 2090}, "monthsOfYear": 2026}'

レスポンス例(抜粋、実際のエンジン出力)

{
  "success": true,
  "data": {
    "engineVersion": "saju-flow-6",
    "kbVersion": "2026.10.11-7",
    "hourKnown": true,
    "natalAmbiguous": null,
    "natal": {
      "score": -37, "result": "중화", "level": "약약",
      "breakdown": { "season": -30, "support": 36, "control": -28, "hidden": -5, "root": 5 },
      "primaryYongshin": "토",
      "shin": { "yongshin": "토", "huishin": "화", "gishin": "목", "gushin": "수", "hanshin": "금" },
      "ruleIds": ["R-SAJU-STR-001", "R-SAJU-STR-018", "R-SAJU-STR-019", "R-SAJU-YONG-170"]
    },
    "daeun": [
      { "startYear": 1997, "endYear": 2006, "startAge": 7,
        "chars": [
          { "pos": "stem", "char": "임", "hanja": "壬", "ohaeng": "수", "sipsin": "식신", "shinRole": "gushin",
            "share": { "support": 0, "control": -8, "hidden": 0, "root": 0, "total": -8 } },
          { "pos": "branch", "char": "오", "hanja": "午", "ohaeng": "화", "sipsin": "정관", "shinRole": "huishin",
            "share": { "support": 0, "control": -10, "hidden": -5, "root": 0, "total": -15 } }
        ],
        "delta": -23, "line": { "value": -60, "clamped": false },
        "relations": [
          { "type": "자형", "from": "daeun", "with": "yearBranch", "a": "오", "b": "오", "ruleId": "R-SAJU-REL-044", "decisionRuleId": "R-SAJU-UN-036" },
          { "type": "육합", "from": "daeun", "with": "hourBranch", "a": "오", "b": "미", "ruleId": "R-SAJU-REL-015", "decisionRuleId": null }
        ],
        "triples": [], "hapPulim": [ ... ] },
      ...
    ],
    "years": [
      { "year": 2026, "daeunIndex": 2,
        "chars": [ { "pos": "stem", "char": "병", "hanja": "丙", ... "share": { ..., "total": -10 } },
                   { "pos": "branch", "char": "오", "hanja": "午", ... "share": { ..., "total": -15 } } ],
        "delta": -25, "line": { "value": -33, "clamped": false },
        "relations": [
          { "type": "천간합", "from": "seun", "with": "monthStem", "a": "병", "b": "신", "ruleId": "R-SAJU-REL-003", "decisionRuleId": null },
          ...
        ],
        "withDaeun": [], "triples": [],
        "hapPulim": [
          { "kind": "existing", "domain": "jiji", "pair": ["오", "미"], "status": "broken_by_dong",
            "reasonCode": "branch_hap_broken", "params": { "incoming": "오", "origin": "seun" },
            "triggeredBy": { "origin": "seun", "value": "오" },
            "reasonFallback": "동기 오(seun) 도래 → 합반 깨짐" },
          { "kind": "new", "domain": "cheongan", "pair": ["병", "신"], "chartValue": "신", "incomingValue": "병", "incomingOrigin": "seun",
            "reasonCode": "new_stem_hap", "params": { "incoming": "병", "origin": "seun", "partner": "신" },
            "reasonFallback": "병(seun) + 원국 신 → 새 천간 합 형성" },
          ...
        ],
        "ipchunNote": false },
      ...
    ],
    "months": [
      { "index": 1, "startsAt": "2026-02-04T04:55:00+09:00",
        "chars": [ { "pos": "stem", "char": "경", ... }, { "pos": "branch", "char": "인", ... } ],
        "delta": 4,
        "relations": [ { "type": "반합", "from": "wolun", "with": "yearBranch", "a": "인", "b": "오", "ruleId": "R-SAJU-REL-024", "decisionRuleId": "R-SAJU-UN-035" }, ... ] },
      ...
    ],
    "compatInputs": {
      "primaryYongshin": "토",
      "surfaceElementCounts": { "목": 0, "화": 2, "토": 2, "금": 3, "수": 1 },
      "surfaceAbsent": ["목"],
      "hourKnown": true,
      "ruleIds": ["R-SAJU-COMPAT-008", "R-SAJU-COMPAT-009", "R-SAJU-COMPAT-010"]
    },
    "caveats": ["R-SAJU-UN-028", "R-SAJU-PRAC-026", "R-SAJU-UN-034"],
    "birthBeforeIpchun": false,
    "assumedLocation": { "correction": "none" },
    "costPoints": 0
  }
}

フィールドの読み方

料金

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
404saju_flow_not_enabledアカウントでこの機能が有効になっていない
400INVALID_DATEbirthDateの形式エラー、または存在しない日付
400INVALID_LUNAR_DATE存在しない旧暦の日付
400INVALID_RANGEtoYearがfromYearより前、または範囲が101年を超える
400INVALID_TIMEbirthTimeがHH:mm形式ではない
400INVALID_LOCATIONbirthLatitude・birthLongitudeの片方だけを送った
409saju_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 / personABirthLongitude
personBBirthLatitude / personBBirthLongitude
number 出生地の座標(両方送ります)。アセンダントの計算と四柱推命の真太陽時補正の両方に使います(四柱推命への適用は2026-10-11から)。座標がない場合、アセンダントはpersonXCountryから、それもなければlangの国の代表座標から推定します(ko → 韓国、ja → 日本、th → タイ/enではアセンダントを省略)
personABirthTimezoneOffset / personBBirthTimezoneOffset number UTCとの差(分)、デフォルト540(KST)。座標と一緒に送ると、四柱推命の補正の標準子午線も決まります(省略時は経度に最も近いタイムゾーン)。personXBirthTimezoneも送った場合はそちらが優先されます
personABirthTimezone / personBBirthTimezone string 出生地のタイムゾーン(IANA、例:"America/New_York"、任意、2026-10-14)。万歳暦APIのtimezoneと同じルールで四柱推命を計算するため、同じ出生情報なら万歳暦APIと同じ四柱になります — ソウル以外では節気の入りの時刻をそのタイムゾーンで読み(夏時間を含む)、座標と一緒に送ると夏時間を除いた標準時差を補正の基準にします。personXBirthTimezoneOffsetより優先され、星座相性のチャートは、出生当時そのタイムゾーンで実際に使われていた時計の時刻(夏時間を含む)で作成します。省略すると従来どおり計算します(出生時刻を韓国時間として読みます)。名前を認識できない場合は省略したものとして計算し、レスポンスにwarnings(UNKNOWN_TIMEZONE、1人につき1件)が付きます
personACalendar · personAIsLeapMonth
personBCalendar · personBIsLeapMonth
string · boolean "lunar"にすると、生年月日を旧暦として受け取り、新暦に変換して計算します(デフォルト"solar")。IsLeapMonth: trueは閏月です。その年にその閏月がない場合や旧暦の日付が存在しない場合は400 INVALID_LUNAR_DATE(課金なし)。どちらか一方でも旧暦で送ると、レスポンスにlunarInput({a, b}、万歳暦APIと同じ形式)が付きます
personACountry / personBCountry string 出生国の2文字の国コード。座標なしでKR・JP・THを送ると、その国の代表経度で四柱推命の時刻を補正します(その他の国は補正なし)。星座の相性でもlangの代わりにこの国でアセンダントを推定します
personAZaSiRule / personBZaSiRule string 子の刻(23時以降)の日柱:"traditional"(デフォルト、翌日の日柱)・"yajaSi"(夜子時、当日の日柱・出生地補正後、23時台の時柱の天干は翌日の日干を基準にします、2026-10-20から)
details boolean デフォルトはfalse。trueにすると、saju.full8(八字の詳細分析)・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のまま)。

出生時刻がわかる人は、出生国と"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"
  }
}

関係の種類(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
stemHap2人の日干の間の干合gather
stemChung2人の日干の間の干沖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 }, ... }
  }
}

注意事項

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
400INVALID_BIRTH_YEARどちらかの生まれ年が1900–2100の範囲外
400INVALID_LUNAR_DATE旧暦の日付が存在しない
400COMPAT_UNAVAILABLEこの日柱の組み合わせの相性データがない
402INSUFFICIENT_BALANCE残高不足

リクエスト例は、上のオプションの例と実行例を参照してください。

性格タイプAPI

MBTIベースの性格診断を提供します。無料のライト版(24問)とプレミアム版(93問)に対応しています。

GET /api/v1/partners/v1/personality-type/questions

性格診断の質問を取得します。無料です。

curl "https://api.hrum.ai/api/v1/partners/v1/personality-type/questions?tier=free" \
  -H "X-Partner-Api-Key: your-api-key"

リクエストパラメータ

パラメータ 型 説明
tier string 診断のバージョン("free"または"premium"、デフォルト:"free")

レスポンス例

{
  "success": true,
  "data": {
    "tier": "free",
    "count": 24,
    "questions": [
      {
        "id": "q_001",
        "text": "갑자기 생긴 모임에도 일단 가본다",
        "choices": [
          { "value": 1, "label": "전혀 그렇지 않다" },
          { "value": 2, "label": "그렇지 않다" },
          { "value": 3, "label": "보통이다" },
          { "value": 4, "label": "그렇다" },
          { "value": 5, "label": "매우 그렇다" }
        ]
      }
    ]
  }
}

POST /api/v1/partners/v1/personality-type

性格診断の回答を送信し、性格タイプを分析します。

curl -X POST https://api.hrum.ai/api/v1/partners/v1/personality-type \
  -H "X-Partner-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "tier": "free",
    "answers": [
      { "questionId": "q_001", "answer": 4 },
      { "questionId": "q_002", "answer": 2 }
    ]
  }'

リクエストパラメータ

パラメータ 型 必須 説明
answers array O 回答の配列 [{ "questionId": "q_001", "answer": 4 }, ...]。questionIdは質問のレスポンスのid(形式q_001)、answerは1–5の整数です。premiumでは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
  }
}

料金

エラーコード

共通エラー(401、400 本文の検証、402、429、503 など)に加えて、このAPIが返すコード:

HTTPコード発生条件
400(なし)質問の取得 — tierがfreeでもpremiumでもない/回答の送信 — 不明なquestionId
400personality_axis_unanswered回答の送信 — premiumで、回答がまったくない軸がある(空の軸はaxesに入ります)
402INSUFFICIENT_BALANCE回答の送信 — premiumで、残高不足

1–5の範囲外の回答は共通の400を返します。いずれも課金されません。

解釈KB API

このAPIは、利用を申請したアカウントにだけ公開されています。それ以外のアカウントには3つのパスすべてで404 kb_saju_explain_not_enabledを返します(課金なし)。利用するにはサポートにお問い合わせください。

四柱推命の命式で成立する関係(合・沖など)と構造(通変星・蔵干など)を、ルールカードと説明文で解説します。LLMを使わないため、同じ入力なら常に同じ結果になります。

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

リクエストパラメータ

パラメータ型必須説明
birthobjectO万歳暦APIのリクエスト本文と同じフィールド(year・month・day・hour?・minute?・timezone・gender・calendar? …)。birth.langは無視されます。birth.timezoneを認識できない場合、レスポンスにwarnings(field: "birth.timezone")が付きます
sectionsstring[]relations・structure・all。省略するとすべて(relations → structureの順)
levelstringL1(デフォルト)・L3。L3の説明がない項目はL1で埋め、fallbackLevelが付きます
langstringkoのみ対応しています
channelstringstable(デフォルト、レビュー済みの説明のみ)・preview(まだレビューしていない説明も含む — 特別に許可されたアカウントのみ。それ以外は403 KB_PREVIEW_NOT_ALLOWED)

リクエスト例

curl -X POST https://api.hrum.ai/api/v1/partners/v1/kb/saju/explain \
  -H "X-Partner-Api-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "birth": {
      "year": 1990, "month": 5, "day": 17, "hour": 14, "minute": 30,
      "timezone": "Asia/Seoul", "gender": "female"
    },
    "sections": ["relations"]
  }'

レスポンス例(抜粋)

{
  "success": true,
  "data": {
    "kbVersion": "2026.10.09-3",
    "kbHash": "sha256:24b9a2d9...",
    "channel": "stable",
    "chart": {
      "pillars": {
        "year":  { "stem": "庚", "branch": "午" },
        "month": { "stem": "辛", "branch": "巳" },
        "day":   { "stem": "壬", "branch": "午" },
        "hour":  { "stem": "丁", "branch": "未" }
      },
      "timeUnknown": false
    },
    "sections": [
      {
        "id": "relations",
        "title": "...",
        "steps": [
          {
            "fact": { "type": "stem_pair", "a": "壬", "b": "丁", "posA": "day", "posB": "hour", "relation": "hap" },
            "factText": "일간 壬과 시간 丁은 천간합(天干合) 관계다.",
            "componentId": "saju:stem_pair:丁壬:hap",
            "rules": [
              { "id": "R-SAJU-REL-004", "kind": "definition", "status": "verified", "sourceCount": 2,
                "statement": "丁과 壬은 천간합 관계이고, 이 짝의 합화 오행은 목(木)이다." }
            ],
            "interp": {
              "meaning": { "text": "丁(정)과 壬(임)은 천간합으로 묶이는 짝이고, ...", "reviewed": false },
              "why": { ... },
              "pitfall": { ... }
            }
          }
        ],
        "absent": [
          { "type": "stem_pair", "a": "庚", "b": "辛", "posA": "year", "posB": "month",
            "note": "庚과 辛은 천간합·천간충 어느 것도 아니다." }
        ]
      }
    ],
    "unregistered": [],
    "pendingReview": []
  }
}

GET /api/v1/partners/v1/kb/rules/{id}

ルールカード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コード発生条件
404kb_saju_explain_not_enabledアカウントが申請していない(3つのパスすべて)
400INVALID_LUNAR_DATE・INVALID_LOCATIONexplain — 旧暦の日付が存在しない/緯度と経度の片方だけを送った
403KB_PREVIEW_NOT_ALLOWEDexplain — channel: "preview"を使えないアカウント(課金なし)
400KB_DOMAIN_UNKNOWNrelease — 対応していないdomain
404KB_RULE_NOT_FOUNDrules — 不明なルールID
503KB_NOT_LOADED解釈KBの版がまだ読み込まれていない。しばらくしてから再試行してください

explainは成功した呼び出しだけを課金し、失敗した呼び出しは₩0として記録されます。

アプリメールAPI

RIDM Appsでホストしているアプリが、新規登録の確認、注文のお知らせ、パスワードの再設定などのトランザクションメール・サービスメールを送るためのAPIです。アプリキー(HRUM_API_KEY、コンソール > マイアプリ > AI連携)でのみ呼び出せます。通常のAPIキーで呼び出すと403 MAIL_APP_KEY_REQUIREDを返します。アプリのコンテナではSMTPポートがブロックされているため、メールはこのAPIで送ってください。

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

リクエストパラメータ

パラメータ型必須説明
tostring | string[]O受信者のアドレス1–10件。表示名付きのアドレス(Name <address>)は受け付けません
subjectstringO件名、1–200文字、改行不可
textstring△本文(プレーンテキスト)。textとhtmlのどちらかが必須です。最大100,000文字
htmlstring△本文(HTML)、最大200,000文字。送信前に整理されます:script・style・iframe・フォーム・イベント属性は削除され、リンクはhttp(s)・mailto・telのみ、画像はhttpsのみ残ります。textがない場合は、HTMLからプレーンテキストの本文を作って一緒に送ります
replyTostring返信先アドレス。ない場合はコンソールで設定したアドレス、それもなければ返信先なしで送信します
attachmentsobject[]添付ファイル最大3件、合計512KB。{ "filename", "contentType", "content" }(contentはbase64)。PDF・PNG・JPEG・GIF・WebP・TXT・CSV・ICSのみ受け付けます
kindstringtransactional(デフォルト)・notification。notificationでは、ワンクリック配信停止のヘッダーが付き、そのアプリの配信を停止したアドレスには送りません(suppressed)

リクエスト例

curl -X POST https://api.hrum.ai/api/v1/partners/v1/mail/send \
  -H "Content-Type: application/json" \
  -H "X-Partner-Api-Key: $HRUM_API_KEY" \
  -d '{
    "to": "user@example.com",
    "subject": "Welcome aboard",
    "text": "Your sign-up is complete. Get started with the link below.",
    "html": "<p>Your sign-up is complete.</p><p><a href=\"https://myapp.ridm.ai\">Get started</a></p>"
  }'

レスポンス例

{
  "success": true,
  "data": {
    "requestId": "7f1c2a3e-…",
    "results": [ { "to": "user@example.com", "status": "sent", "messageId": "<…>" } ],
    "sent": 1,
    "chargedWon": 0
  }
}

statusはsent(メールサーバーが受け付けた)・failed(送信できなかった — 課金なし)・suppressed(アドレスがバウンスまたはスパム報告をしたため、もしくはそのアプリのnotificationメールの配信を停止したため送らなかった)のいずれかです。

上限と料金

項目内容
月間の含まれる通数プランに含まれます(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コード説明
400MAIL_INVALID不正なリクエスト。reasonに理由が入ります(invalid_recipient、too_many_recipients、subject_invalid、advertising_not_allowed、body_required、attachment_type_not_allowed、attachments_too_largeなど)
402insufficient_credit追加送信の支払いに必要なクレジットが足りない。何も送信されません
403MAIL_APP_KEY_REQUIREDアプリキーではないキーで呼び出した
403APP_NOT_ACTIVEキーに紐づくアプリが動いていない
402MAIL_OVERAGE_UNPAID未払いの追加メール料金が残高を超えている。チャージすると未払い分が差し引かれ、送信が再開します(含まれる通数の範囲内の送信は引き続き使えます)
403MAIL_EMAIL_UNVERIFIEDメール認証済みのコンソールアカウントがない
403MAIL_SUSPENDEDスパム報告やバウンスの基準を超えたため、または運営者が停止したため、このアプリのメール送信が停止されている
429MAIL_RATE_LIMITED1分あたりの上限を超えた。retryAfterSecondsの後に再送してください
429MAIL_DAILY_CAP_EXCEEDED1日の上限を超えた。韓国時間の0時に再開します
429MAIL_MONTHLY_LIMIT今月の含まれる通数を使い切った(無料プラン、または追加送信がオフ)
503MAIL_UNAVAILABLEメールサーバーが利用できない。しばらくしてから再試行してください

Webメタバースにリアルタイムの訪問者数を付ける

Three.jsで作ったWebの3D空間や通常のWebページに「いまN人がオンライン」と表示する無料の機能です。コンソール > 訪問者数でサイトを登録すると、公開サイトキー(pk_presence_…)と1行のスクリプトが発行されます。キーやログインなしで、ブラウザから直接呼び出します。

スクリプトを追加する

コンソール > 訪問者数で取得した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の付いたすべての要素に入れます。数字が届くまでは空のままです。

数字を自分で使う

スクリプトは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/directoryMetamoaへの共有に同意したサイトの一覧(名前・アドレス・訪問者数)。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回だけ表示されるため、サーバーの環境変数に保存し、ページやブラウザのコードには絶対に入れないでください。再発行すると、以前のサーバーキーはすぐに使えなくなります。

ルームごとの人数(任意)

自社サーバーが人をルーム(チャンネル、インスタンス)に分けている場合は、同じcountの本文でルームごとの人数と定員を送れます。ルームサーバーは、新しく入る人をどのルームに入れるか選ぶときにGET …/roomsで読み戻します。ルームごとの数字はサーバーキーでのみ読み取れ、公開の照会(online・directory)やpresence.jsには表示されません。全体の訪問者数はこれまでどおりonlineで別に送ってください(ルームの合計からは計算しません)。

POST /api/v1/partners/v1/presence/sites/pk_presence_…/count
X-Presence-Secret: sk_presence_…
Content-Type: application/json

{
  "online": 98,
  "rooms": [
    { "id": "studio-1", "n": 30, "cap": 30 },
    { "id": "studio-2", "n": 28, "cap": 30 },
    { "id": "studio-3", "n": 40, "cap": 50 }
  ]
}

// 200
{ "success": true, "data": { "online": 98, "reportedAt": "2026-10-31T09:00:00.000Z" } }
GET /api/v1/partners/v1/presence/sites/pk_presence_…/rooms
Authorization: Bearer sk_presence_…

// 200
{ "success": true, "data": {
  "rooms": [
    { "id": "studio-1", "n": 30, "cap": 30, "free": 0 },
    { "id": "studio-2", "n": 28, "cap": 30, "free": 2 },
    { "id": "studio-3", "n": 40, "cap": 50, "free": 10 }
  ],
  "reportedAt": "2026-10-31T09:00:00.000Z"
} }

サーバーキーは自社サーバーにだけ置いてください。sk_presence_…がブラウザのコード、アプリ、公開リポジトリに入ってしまうと、誰でも訪問者数を変更できてしまいます。環境変数やシークレットストアに入れ、漏れた場合はコンソール > 訪問者数ですぐに再発行してください。

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が運営するディレクトリに表示されます。サイトアドレスが許可オリジンと一致しない場合は表示されません。いつでもオフにできます。

プライバシー

エラー

HTTPコード説明
400PRESENCE_BAD_REQUEST・INVALID_BODYsiteKeyまたはsidの形式が不正、または本文がJSONではない
401PRESENCE_SECRET_REQUIREDサーバーキーがない、または間違っている(公開キーを送った場合を含む) — countのみ
403PRESENCE_ORIGIN_NOT_ALLOWEDOriginがない、または許可オリジンではない
404PRESENCE_SITE_NOT_FOUND不明なキー、または無効化されたキー
413PAYLOAD_TOO_LARGE本文が1KBを超えている
429PRESENCE_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で、発行時に人がチェックしたトークンでのみ有効です。

コンソール管理トークン

  1. AIは実行したい内容(何を · 金額 · 対象)を指定してPOST /api/v1/partners/v1/console-ai/consentsを呼び出し、consentUrlとcodeを受け取ります。
  2. AIはそのリンクをユーザーに見せます(MCPならブラウザで開くこともできます)。
  3. ユーザーがコンソールにログインした状態でリンクを開くと、リクエスト内容がすべて(金額 · 対象 · 名前)「AIによるリクエスト」ラベル付きで表示されます。ユーザーは内容を確認して「同意」を押します。支払い自体も、その後Toss決済画面で人が行います。
  4. AIはGET /console-ai/consents/{code}で承認を確認し、書き込みリクエストの本文にconsentCodeを入れて処理を続けます。

同意コードは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 · usedread(最初のトークンはpoll secret)—
GET /me · GET /token自分のアカウント · このトークンの権限read—
GET /statusはじめにチェックリスト(API · ホスティング · 決済の状況と次のステップ)read—
GET /keysAPIキー一覧(プレフィックスのみ)read—
GET /credit · GET /credit/transactionsクレジット残高 · 履歴(offset、limit ≤ 100)read—
GET /usage期間別の呼び出し数と利用額(from、to)read—
GET /hostingホスティングの利用資格 · プラン · アプリの状況read—
GET /seller · GET /payouts販売者の状況(本人確認情報を除く)· 精算履歴read—
POST /keysAPIキーを発行({label?})keyskey_issue
POST /keys/{id}/rotate新しいキーを発行+このキーを即時無効化keyskey_rotate
POST /keys/{id}/revokeキーを失効(元に戻せません)keyskey_revoke
POST /credit/topup-linkチャージ決済リンク({planKey})creditcredit_topup_link
POST /credit/refund-preview返金可能額を計算(返金は申請しません)creditcredit_refund_preview
POST /hosting/applyホスティングを申し込む({planKey, subdomain, recurringConsent?})hostinghosting_apply
POST /hosting/apps/{id}/cancelホスティングを解約hostinghosting_cancel
POST /seller/apply-link販売者登録画面へのリンクsellerseller_apply_link

書き込みリクエストの本文は、同意リクエストのpayloadと同じ値+consentCodeです。新しいAPIキーは、そのレスポンスで1回だけ表示されます。

カード番号と販売者の本人確認情報は、AI経路では一切受け付けません。カード決済はToss決済画面で行い、販売者の本人確認情報・口座・規約への同意は人がコンソール画面で入力します。payloadに定義済みフィールド以外の値が含まれている場合は、400 UNKNOWN_FIELDで拒否されます。

エラーコード

コードHTTP意味
MGMT_TOKEN_INVALID401トークンがない、期限切れ、または失効済み。新しく取得してください
MGMT_SCOPE_DENIED403このトークンに必要な書き込み権限がありません(scopeフィールド)。その権限にチェックを入れて新しく発行してください
ACCOUNT_SUSPENDED403停止中のアカウント
CONSENT_REQUIRED400書き込みリクエストにconsentCodeがない
CONSENT_PENDING409人がまだ同意していない
CONSENT_DENIED403人が拒否した
CONSENT_EXPIRED41010分が過ぎて期限切れ
CONSENT_USED409同意コードは使用済み
CONSENT_MISMATCH409現在のリクエストが同意した内容(金額 · 対象)と異なる
CONSENT_NOT_FOUND404不明なコード、または別アカウントのコード
INVALID_CONSENT_PAYLOAD400payloadの値が不正(fieldフィールド)
UNKNOWN_FIELD400AI経路で受け付けないフィールドが含まれている
CONSENT_RATE_LIMITED429同意リクエストが多すぎる
MGMT_TOKEN_LIMIT409有効なトークンがすでに10個あるため、これ以上発行できない
NOT_AVAILABLE404まだ公開されていないメニュー

MCPから使う

HRUM MCP(@hrum/mcp 0.2.0)をインストールすると、上記の流れをそのままツールとして使えます。トークン・APIキー・poll secretはモデル(会話)に一切現れず、このコンピューターの設定フォルダと.env.localにのみ保存されます。

claude mcp add hrum -- npx -y https://console.hrum.ai/mcp/hrum-mcp-0.3.6.tgz
ツール内容
hrum_ai_connect · hrum_ai_connect_status管理トークンの同意リンクを作成 → 承認されたらトークンを保存(値は表示されません)
hrum_status · hrum_keys_list · hrum_credit · hrum_credit_history · hrum_usage · hrum_hosting_status · hrum_seller_status · hrum_payouts_list照会
hrum_consent_request · hrum_consent_status書き込みへの同意をリクエスト · 状況を確認
hrum_key_issue · hrum_key_rotate · hrum_key_revokeキーの発行・再発行(新しいキーは.env.localにのみ保存)· 失効
hrum_topup_link · hrum_refund_previewチャージリンク · 返金可能額
hrum_hosting_apply · hrum_hosting_cancel · hrum_seller_apply_linkホスティングの申し込みと解約 · 販売者登録リンク

アカウント照会API

クレジット残高と利用量を確認するためのAPIです。ヘッダーにX-Partner-Api-Keyを含める必要があります。

GET /api/v1/partners/v1/credits/balance

現在のクレジット残高を取得します。

リクエスト

curl -X GET https://api.hrum.ai/api/v1/partners/v1/credits/balance \
  -H "X-Partner-Api-Key: your-api-key"

レスポンス

{
  "success": true,
  "data": {
    "balanceWon": 25000,
    "lastUpdated": "2026-10-09T05:12:30.000Z",
    "estimatedMonthEndBalance": 15000,
    "warningThreshold": 5000,
    "lowBalanceActive": false
  }
}

warningThresholdはパートナーごとに異なります — max(₩5,000、直近の有料チャージ額の20%)。lowBalanceActiveは、残高がこのしきい値を下回り、残高不足の警告が有効になっているかどうかを示します。APIでチャージするエンドポイントはありません — コンソール > 請求でチャージしてください。このAPIには固有のエラーコードはなく、共通エラーのみです。

GET /api/v1/partners/v1/usage/logs?limit=50&offset=0

API呼び出しの記録を新しい順に取得します。各項目にはid · timestamp · endpoint(短い名前、例:manseryeok)· statusCode · costWon · responseTimeMs(現在は常にnull)があり、該当する場合はidempotencyKey · model · endUserId · cachedTokensも含まれます。

リクエストパラメータ

パラメータ 型 説明
limit number 取得する件数(デフォルト:50、最大:200)
offset number オフセット(デフォルト:0)
endpoint string エンドポイントの短い名前で絞り込み(例:manseryeok)。allまたは省略ですべて
dateFrom · dateTo string 期間(YYYY-MM-DD)。省略すると制限なし

リクエスト

curl "https://api.hrum.ai/api/v1/partners/v1/usage/logs?limit=50&offset=0&endpoint=manseryeok" \
  -H "X-Partner-Api-Key: your-api-key"

レスポンス

{
  "success": true,
  "data": {
    "logs": [
      {
        "id": "12345",
        "timestamp": "2026-08-10T14:30:00.000Z",
        "endpoint": "manseryeok",
        "statusCode": 200,
        "costWon": 50,
        "responseTimeMs": null,
        "idempotencyKey": "order-8812"
      }
    ],
    "total": 1234,
    "pagination": {
      "limit": 50,
      "offset": 0,
      "hasMore": true
    }
  }
}

GET /api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31

期間ごとの利用統計を取得します。日付を省略すると、当月全体が対象です。dailyBreakdownの日付は韓国時間(KST)です。

リクエストパラメータ

パラメータ 型 説明
dateFrom string 開始日(YYYY-MM-DD)
dateTo string 終了日(YYYY-MM-DD)

リクエスト

curl "https://api.hrum.ai/api/v1/partners/v1/usage/summary?dateFrom=2026-08-01&dateTo=2026-08-31" \
  -H "X-Partner-Api-Key: your-api-key"

レスポンス

{
  "success": true,
  "data": {
    "dateRange": { "from": "2026-08-01", "to": "2026-08-31" },
    "totalCalls": 1234,
    "totalCostWon": 6170,
    "byEndpoint": [
      {
        "endpoint": "manseryeok",
        "calls": 1234,
        "costWon": 6170,
        "percentOfTotal": 100
      }
    ],
    "dailyBreakdown": [
      {
        "date": "2026-08-10",
        "calls": 150,
        "costWon": 750
      }
    ]
  }
}

エラーコード(利用ログ · 集計)

共通エラーのほかに、YYYY-MM-DD形式でない日付や、負のlimit・offsetはコードなしの400を返します。照会は無料です。

GET /api/v1/partners/v1/status/upstream

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コード発生条件
429GUEST_QUOTA_EXCEEDED同じIPから今月5回を超えて呼び出した(ネイタルチャートのゲスト用エンドポイントと合算)
400INVALID_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用語集を使ってください。値は上記の天干・地支・五行と、通変星(비견 比肩 · 겁재 劫財 · 식신 食神 · 상관 傷官 · 편재 偏財 · 정재 正財 · 편관 偏官 · 정관 正官 · 편인 偏印 · 정인 正印)です。

率直さ(candor)

t、f(デフォルト)— 大文字と小文字は区別しません。旧値のbluntはtに、balanced · gentleはfに正規化されます。それ以外の値は400を返します(率直さ(仮称))

エラーコード

すべてのAPIは、以下の共通エラーを同じ形で返します。各APIセクションのエラー表には、そのAPI固有のコードだけを載せています。リクエストは次の順に確認され、あるステップで失敗すると、それ以降のステップは実行されません。

  1. セキュリティルール — ブロック対象のUser-AgentはAPIサーバーに届く前に遮断されます(403、HTML本文、error 1010)。APIキーの確認より前に起きるため、401ではなく403になります
  2. サービス保護上限 — 同じIPからの全リクエストに対する1分あたりの上限(429、codeなし)
  3. APIキー — X-Partner-Api-Keyの確認(401)
  4. 機能の有効化 — アカウントで有効になっていない機能(404 *_not_enabled)
  5. リクエスト制限 — コンソールで設定した1秒あたり・1日あたりの制限(429 RATE_LIMIT_EXCEEDED)
  6. 本文の検証 — フィールド名、型、範囲(400)
  7. 残高 · 計算 · 呼び出し — 残高不足(402)、API固有の入力エラー、外部モデルのエラー

共通エラー

HTTP コード 発生条件 課金
400(なし)本文の検証に失敗 — 表にないフィールドを送った、または型や範囲が誤っている。messageは文字列の配列ですなし
401(なし)X-Partner-Api-Keyがない、無効なキー、失効済みのキー、無効なアカウントなし
402INSUFFICIENT_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分以内に再試行してくださいなし
429RATE_LIMIT_EXCEEDEDコンソールで設定した1秒あたりまたは1日あたりの制限を超過。本文にretryAfterSecondsがあり、Retry-Afterヘッダーも付きますなし
500(なし)サーバーエラー。このリクエストですでに差し引かれた金額は、レスポンスの後に返却されます返金
503SERVICE_DEGRADED一時的なデータベース接続の問題。Retry-After: 30 — 30秒後に再試行してください返金

エラーレスポンス本文の形式:{"success": false, "statusCode": 400, "code": "INVALID_LOCATION", "message": "...", "timestamp": "..."} — codeはある場合にのみ含まれます。分岐にはstatusCodeとcodeを使い、messageの文言には頼らないでください。

// 401 — key missing or invalid
{ "success": false, "statusCode": 401, "message": "Invalid or missing API key", "error": "Unauthorized", "timestamp": "2026-10-12T03:00:00.000Z" }

// 400 — body validation failed (message is an array)
{ "success": false, "statusCode": 400, "message": ["property foo should not exist", "month must not be greater than 12"], "error": "Bad Request", "timestamp": "2026-10-12T03:00:00.000Z" }

// 404 — feature not enabled for the account (message: "This feature is not available yet")
{ "success": false, "statusCode": 404, "code": "ziwei_not_enabled", "message": "아직 열리지 않은 기능입니다", "timestamp": "2026-10-12T03:00:00.000Z" }

// 429 — request limit set in the console (message: "Per-second request limit exceeded. You can adjust it in console > API keys > Request limits.")
{ "success": false, "statusCode": 429, "code": "RATE_LIMIT_EXCEEDED", "message": "초당 요청 제한을 초과했어요. 콘솔 > API 키 > 요청 제한에서 조정할 수 있어요.", "retryAfterSeconds": 1, "timestamp": "2026-10-12T03:00:00.000Z" }

よく見られるAPI固有のコード:422 処理できない入力(PROMPT_TOO_LONG、EXTRACTION_FAILED)、503 一時的に利用不可(例:解説文を読み込めなかった場合。課金なし)、504 外部モデルのタイムアウト。ゲスト体験の回数枠は429 GUEST_QUOTA_EXCEEDEDです。

レスポンスの警告(warnings)

リクエストは成功したものの、入力の一部が認識できずデフォルト値を使った場合、成功レスポンスの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)を設定してください。空欄のままにすると、上記のサービス保護上限のみが適用されます。

課金

すべての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枚あたり固定料金 — 料金表

ゲストテスト

冪等性

成功したリクエストはすべて個別に課金されます。同じリクエストを再送すると、再計算・再生成されて再び課金されるため、再試行による重複や同じ入力の再利用には、クライアント側でレスポンスを保存して対応してください(例:リクエストのハッシュをキーにしたキャッシュ)。

X-Idempotency-Keyヘッダー(最大128文字 — それより長い場合は先頭128文字が記録されます)は引き続き受け付けますが、課金を防ぐものではありません。送ったキーは利用ログのidempotencyKeyにそのまま記録されるため、どのリクエストがどの呼び出しで処理されたかを、自社の注文IDやジョブIDと照合するのに使えます。

例外:人相・手相占いでは、同じキーと同じ本文を24時間以内に再送すると、新たに課金されずに最初の結果が返ります(再試行と再送信)。

例外:姓名分析では、同じキーと同じ本文を24時間以内に再送すると、新たに課金されずに最初の結果が返ります(再試行と再送信)。

サポート

連携中に行き詰まったときや、レスポンスがドキュメントと異なるときはお知らせください。

お問い合わせ連絡先
技術サポート · 障害報告 · 提携 contact@float.do

お問い合わせの際に以下も送っていただくと、より早く確認できます。

規約と個人情報の取り扱いについては、利用規約(韓国語)とプライバシーポリシー(韓国語)をご覧ください。