Access CAFE engine's Saju analysis via REST API. One API key gives access to 10 MCP tools.
Your first API call in 3 lines:
curl -X POST https://24plus.ai.kr/api/v1/cafe/fortune_data \
-H "X-API-Key: pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"birth":"199001151030","gender":1,"period":"yl"}'All requests require authentication. Two methods supported:
# 방법 1: X-API-Key 헤더 (권장)
curl -H "X-API-Key: pk_live_your_api_key_here" ...
# 방법 2: Bearer Token
curl -H "Authorization: Bearer pk_live_your_api_key_here" ...Use API keys server-side only. Never expose in client code. If compromised, request immediate revocation.
Set auth_type to 'api_key_ip' to restrict calls to registered IPs. Recommended for production.
https://24plus.ai.kr/api/v1/cafe/{func_name}Single endpoint routes to 10 MCP tools via func_name.
# API 목록 조회 (인증 불필요)
GET /api/v1/cafe/_list
→ { "tools": ["fortune_data","fortune_reading","cafe_ncode","daily_fortune",...] }Applies to most tools. term_search and cafe_research only require query, not birth/gender.
| Field | Type | Description | |
|---|---|---|---|
birth | string | required | Birth datetime YYYYMMDDHHMM (solar) |
gender | int | required | Gender (0: female, 1: male) |
name | string | optional | Name (optional) |
is_lunar | int | optional | Lunar calendar (0: solar, 1: lunar, 2: leap lunar) |
ws_flag | int | optional | Year pillar ref (0: Ipchun, -1: Dongji) |
{
"result": { ... }, // CAFE 엔진 분석 결과
"usage": {
"rpm_remaining": 58, // 분당 잔여
"rpd_remaining": 9945, // 일당 잔여
"monthly_remaining": 298721 // 월당 잔여
},
"meta": {
"function": "fortune_data", // 호출된 MCP 도구
"response_time_ms": 142, // 응답 시간 (ms)
"partner": "dangamsoft" // 파트너 코드
}
}8 APIs (MCP Tool names) · ● = extra params
fortune_dataFortune raw data (major/yearly/monthly/daily)+paramsperiod | string | bl/yl/ml/dl |
fortune_readingFortune flow analysis (events, changes, weights)+paramstype | string | events/summary | |
period | string | bl/yl/ml/dl |
daily_fortuneFortune service (life, activity, date selection)+paramsscope | string | required | Scope of fortune reading |
period | string | Period (depends on scope) | |
value | string | Target: year/month/day | |
selected_luck | string[] | Activity items for choice/activity scope |
cafe_ncodePersonality Analysis (MBTI+Saju personality type)+paramstype | string | all/tendency/career/luck | |
year | int | Analysis year (default: current) |
compatibilityRelationship analysis (1:1 or group compatibility)+paramsrel_birth | string | required | Partner birth datetime |
rel_gender | int | required | Partner gender (0: F, 1: M) |
relation_type | string | Relation type |
namingAI naming (Yongshin-based, 9 modes)+paramsfamily_name | string | required | Family name |
mode | string | Naming mode |
cafe_researchClassic text search (RAG-based)+paramsquery | string | required | Search query |
top_k | int | Number of results | |
category | string | Category filter |
term_searchSaju terminology search+paramsquery | string | required | Search term |
field | string | Search field |
Use the tool names below for MCP integration. Each tool branches into sub-features via parameters.
cafe_ncodetype: all, tendency, career, luckfortune_dataperiod: bl(대운), yl(세운), ml(월운), dl(일운)fortune_readingtype: events, summary | period: bl, yl, ml, dldaily_fortunescope: total, life, activity, choice, yearly, monthly, dailycompatibilityrel_birth (필수), rel_gender (필수), relation_typenamingfamily_name (필수), mode: basic/yongshin/hanja/stroke/full/evalcafe_researchquery (필수), top_k, categoryterm_searchquery (필수), field: terms/keywords/dictThree tiers of rate limiting per API key. Defaults adjustable.
| Limit | Default | Reset | Exceeded |
|---|---|---|---|
| RPM | 60 | Per min | 429 + Retry-After: 60 |
| RPD | 10,000 | Midnight KST | 429 |
| Monthly | 300,000 | 1st of month | 429 |
Check remaining quota in usage field of each response.
| Code | Description | Action |
|---|---|---|
| 400 | Bad request (invalid params / unknown function) | Check params |
| 401 | Unauthorized (missing or invalid API key) | Check API key |
| 403 | Forbidden (no permission / IP blocked / account suspended) | Request permission |
| 429 | Rate limit exceeded (RPM/RPD/Monthly) | Wait per Retry-After |
| 502 | CAFE engine unreachable | Retry (max 3) |
| 504 | CAFE engine timeout (30s) | Retry (max 3) |
// 일반 에러
{ "error": "Rate limit exceeded: 60 RPM" }
// CAFE 엔진 에러
{ "error": "CAFE engine error", "detail": { ... } }Enter your API key and test live API calls.
import requests
API_KEY = "pk_live_your_api_key_here"
BASE_URL = "https://24plus.ai.kr/api/v1/cafe"
def call_cafe(func_name, params):
resp = requests.post(
f"{BASE_URL}/{func_name}",
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
json=params, timeout=30,
)
resp.raise_for_status()
return resp.json()
# 사주 기본 정보
result = call_cafe("fortune_data", {
"birth": "199001151030", "gender": 1, "period": "yl",
})
print(result["result"])
print(f"RPM 잔여: {result['usage']['rpm_remaining']}")
# 관계분석
compat = call_cafe("compatibility", {
"birth": "199001151030", "gender": 1,
"rel_birth": "199205201400", "rel_gender": 0,
})const API_KEY = "pk_live_your_api_key_here";
const BASE_URL = "https://24plus.ai.kr/api/v1/cafe";
async function callCafe(funcName, params) {
const res = await fetch(`${BASE_URL}/${funcName}`, {
method: "POST",
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify(params),
signal: AbortSignal.timeout(30000),
});
if (!res.ok) {
const err = await res.json();
throw new Error(`${res.status}: ${err.error}`);
}
return res.json();
}
// 오늘의 운세
const fortune = await callCafe("daily_fortune", {
birth: "199001151030", gender: 1, scope: "total",
});
// 작명
const names = await callCafe("naming", {
birth: "202401150800", gender: 0, family_name: "김",
});import requests
from time import sleep
def call_with_retry(func_name, params, max_retries=3):
for attempt in range(max_retries):
try:
resp = requests.post(
f"{BASE_URL}/{func_name}",
headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
json=params, timeout=30,
)
if resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 60))
sleep(retry_after)
continue
if resp.status_code in (502, 504):
sleep(2 ** attempt)
continue
resp.raise_for_status()
return resp.json()
except requests.Timeout:
if attempt == max_retries - 1: raise
raise Exception("Max retries exceeded")Need help?
API key, permissions, rate limits → 24Plus admin. Technical issues → partner@24plus.kr