# SAZU 사주 API · 만세력 API 문서

> 생년월일·출생시간·성별을 보내면 사주팔자(원국)·만세력·대운·오행·신강신약·신살·합형충파해·격국·용신을
> JSON 으로 돌려주는 한국어 REST API 문서입니다. 이 문서는 https://www.sazu.app/manse-api/docs 의 마크다운 사본이며,
> 두 문서의 내용은 같은 원본에서 생성됩니다.

- 공식 문서(HTML): https://www.sazu.app/manse-api/docs
- API 기준 주소: `https://api.sazu.app`
- 최초 공개: 2025-11-21 · 최종 개정: 2026-08-29
- 문의: contact@sazu.app

## 인증

모든 요청에 API 키가 필요합니다. 다음 두 헤더 중 하나를 쓰세요.

```http
x-api-key: YOUR_API_KEY
Authorization: Bearer YOUR_API_KEY
```

키는 대시보드에서 발급합니다: https://www.sazu.app/manse-api/dashboard/keys
키는 서버 환경변수에만 두고 브라우저·앱 코드로 내려보내지 마세요. 브라우저에서 직접 호출하면 키가 화면 소스에 그대로 노출됩니다.

## 5분 시작하기

```bash
curl -X POST https://api.sazu.app/v1/sazu/calculate \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"birthYear":1998,"birthMonth":5,"birthDay":19,"birthHour":10,"birthMinute":0,"isFemale":false,"isLunar":false,"birthCity":"서울"}'
```

위 입력값은 아래 "Free 샌드박스" 의 샘플 프로필이라 Free 키로도 정상 응답이 나옵니다.

## Free 샌드박스 — 샘플 프로필만 계산합니다

2026년 8월 25일 이후 발급된 Free 키는 샌드박스로 동작하며, 그 이전 키는 2026년 10월 1일부터 전환됩니다. 아래 샘플 프로필 5종의 입력값과 **정확히 일치**할 때만 응답하며,
그 응답은 Pro 와 동일한 15개 모듈 구조를 고정 데이터로 담습니다. 응답시간까지 실제와 같게 모사하므로
연동·화면·로딩 UX 검증은 그대로 하실 수 있습니다.

일치하지 않는 생년월일은 `400 SAMPLE_PROFILE_REQUIRED` 로 응답합니다. **오류가 아니라 Free 플랜의 정상 동작입니다.**
응답의 `error.details.sampleProfiles` 에 아래 목록이 그대로 포함되므로 코드에서 바로 참조할 수 있습니다.
성공 응답에는 `meta.sample` · `meta.sampleProfile` 이 붙어 샘플 여부를 구분할 수 있습니다.

| sampleProfile | 특성 | 입력값 | 확인 용도 |
| --- | --- | --- | --- |
| `strong-male` | 신강 · 남 · 합충 풍부 | 1998-05-19 10:00 · 남 · 서울 | 관계 목록이 길 때의 레이아웃·줄바꿈 |
| `weak-female` | 신약 · 여 · 대운 역행 | 1970-05-05 10:00 · 여 · 서울 | 대운이 역순일 때의 정렬·나이 표기 |
| `unknown-hour` | 출생시간 미상 (시주 없음) | 1985-08-12 · 시각 null · 남 · 서울 | 기둥 하나가 비는 화면·null 처리 |
| `balanced` | 중화 · 관계 희소 | 1972-05-19 10:00 · 남 · 서울 | 합충이 거의 없을 때의 빈 상태 |
| `rich-sinsal` | 신살 풍부 · 여 | 1993-11-19 10:00 · 여 · 서울 | 뱃지가 많을 때의 넘침·접힘 |

실제 생년월일 계산이 필요하면 Pro 플랜을 이용하세요.

## 엔드포인트

### POST /v1/sazu/calculate

사주 분석 (핵심)

| 필드 | 타입 | 필수 | 설명 |
| --- | --- | --- | --- |
| `birthYear` | number | 필수 | 출생년도 (1900~2100). 정수 문자열("1990") 도 허용. |
| `birthMonth` | number | 필수 | 출생월 (1~12). 정수 문자열("3") 도 허용. JavaScript Date.getMonth() 의 0~11 그대로 전송하면 거부됩니다. |
| `birthDay` | number | 필수 | 출생일 (1~31). 정수 문자열도 허용. |
| `birthHour` | number | null | 선택 | 출생시 (0~23), 모르면 null. 정수 문자열도 허용. |
| `birthMinute` | number | 선택 | 출생분 (0~59), 기본값 0. 정수 문자열도 허용. |
| `isFemale` | boolean | 선택 | 여성 여부. 누락 시 기본값 false(남성)로 처리되며 응답 헤더 X-Input-Coerced 와 meta.warnings 로 통지합니다. 성별은 사주 결과(대운 진행 방향·해석)에 큰 영향을 주므로 명시 권장. |
| `isLunar` | boolean | 선택 | 음력 여부, 기본값 false. 음력으로 보내실 때는 윤달 여부(isLeapMonth)를 함께 확인하세요 — 아래 항목 참조. |
| `isLeapMonth` | boolean | 선택 | 음력 입력이 윤달인지 여부, 기본값 false. isLunar: true 일 때만 사용합니다. 윤달이 드는 해에는 같은 달이 두 번 오므로 연·월·일만으로는 날짜가 하나로 정해지지 않습니다. 예를 들어 1998년에는 5월이 두 번(평5월·윤5월) 있어 음력 1998-05-15 는 양력 6월 9일과 7월 8일 두 가지가 되고, 29일 차이라 월주·일주·시주가 모두 달라집니다. 윤달 출생이면 true 를 보내주세요. [2026-08-22 반영] |
| `birthCity` | string | 선택 | 출생 도시, 기본값 "서울" |
| `locale` | "ko" | "han" | 선택 | 한글 또는 한자, 기본값 "ko" |
| `modules` | string[] | 선택 | 포함할 모듈 ID 목록. 생략 시 플랜별 기본 모듈 |
| `decadeCount` | number | 선택 | 대운 개수 (11~20, 기본 13) |
| `trueSolarTime` | boolean | 선택 | 진태양시(경도차 + 균시차) 적용 여부, 기본 false. false = 한국 관습(자시 23:30, 경도차만). true = 한국천문연구원 방식 진태양시(자시 23:00, 균시차 포함). [API v1.1.0(2026-07-01)+] 자세한 차이는 §birthCity 참조. |
| `detail` | "minimal" | "standard" | "full" | 선택 | 응답 상세 수준. minimal(값만), standard(핵심해석, 기본), full(전체) |

```bash
# 필수 필드는 birthYear / birthMonth / birthDay (camelCase, "birth" 접두사).
# 주의: year / month / day (접두사 없음) 는 음양력 변환(/v1/calendar/convert) 전용입니다.
# Free(샌드박스) 키는 문서의 샘플 프로필 입력과 일치할 때만 응답합니다 — 아래 "Free 샌드박스" 참고.
curl -X POST https://api.sazu.app/v1/sazu/calculate \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "birthYear": 1990,
    "birthMonth": 3,
    "birthDay": 15,
    "birthHour": 14,
    "birthMinute": 30,
    "isFemale": false,
    "isLunar": false
  }'
```

### GET /v1/sazu/modules

사용 가능한 모듈 목록

### GET /v1/me

현재 키의 tier · 분당/월간 한도 · 사용량 · 재설정 시각 · ban 상태. 응답: data: { tier, rateLimitPerMinute, monthlyQuota, used, remaining, quotaCycleStart, quotaResetAt, banned, bannedUntil }

### GET /v1/me/errors

본인 키로 발생한 최근 4xx/5xx 오류 이력 (15일 retention)

| 필드 | 타입 | 필수 | 설명 |
| --- | --- | --- | --- |
| `limit` | number | 선택 | 반환 개수 (1~100, 기본 20) |
| `offset` | number | 선택 | 페이징 (기본 0) |
| `status` | "all" | "4xx" | "5xx" | "400" | "500" | 선택 | status 필터 (기본 all) |
| `endpoint` | string | 선택 | 엔드포인트 정확 일치 필터 (예: /v1/sazu/calculate) |
| `since` | ISO 8601 string | 선택 | 조회 시작 시각, 기본 24시간 전, 최대 15일 (DB retention) |

### POST /v1/calendar/convert

음양력 변환

| 필드 | 타입 | 필수 | 설명 |
| --- | --- | --- | --- |
| `year` | number | 필수 | 년도. (사주 분석 /v1/sazu/calculate 의 birthYear 와 다른 필드명이니 주의) |
| `month` | number | 필수 | 월 |
| `day` | number | 필수 | 일 |
| `direction` | "toSolar" | "toLunar" | 필수 | 변환 방향. toSolar = 음력→양력, toLunar = 양력→음력 |
| `isLeapMonth` | boolean | 선택 | 윤달 여부, 기본값 false. direction: "toSolar"(음력→양력) 일 때만 사용합니다. 윤달이 드는 해에는 같은 달이 두 번 오므로, 음력 1998-05-15 는 isLeapMonth 값에 따라 양력 6월 9일(평5월) 또는 7월 8일(윤5월)이 됩니다. 반대 방향(toLunar)은 입력 날짜가 하나로 정해지므로 보내실 필요가 없고, 결과의 isLeap 로 윤달 여부를 알려드립니다. [2026-08-22 반영] |

```bash
# 음양력 변환은 year / month / day (접두사 없음) 를 씁니다.
# 사주 분석(/v1/sazu/calculate)의 birthYear / birthMonth / birthDay 와 다릅니다.
curl -X POST https://api.sazu.app/v1/calendar/convert \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "year": 1990,
    "month": 3,
    "day": 15,
    "direction": "toLunar"
  }'

# 음력→양력에서 윤달이면 isLeapMonth 를 함께 보냅니다.
# 1998년 음력 5월은 평5월(→ 6/9)과 윤5월(→ 7/8) 두 가지입니다.
curl -X POST https://api.sazu.app/v1/calendar/convert \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "year": 1998,
    "month": 5,
    "day": 15,
    "direction": "toSolar",
    "isLeapMonth": true
  }'
```

## 분석 모듈 (15개)

`modules` 를 생략하면 플랜 기본 조합이 반환됩니다. 필요한 모듈만 배열로 지정하면 응답이 작아집니다.

| id | 이름 | 플랜 | 설명 |
| --- | --- | --- | --- |
| `fourPillars` | 사주 원국 | Free·Pro | 천간·지지·십성·12운성·12신살·납음·지장간 포함 |
| `decadeFortune` | 대운 | Free·Pro | 10년 단위 대운 흐름, 순행/역행, 시작 나이 |
| `elements` | 오행 분포 | Free·Pro | 목화토금수 분포, 천간/지지 별도 집계 |
| `summary` | 분석 요약 | Free·Pro | 오행 균형, 조화/갈등, 대운을 점수·등급으로 요약 |
| `sinStrength` | 신강/신약 | Free·Pro | 득령·득지·득세 3원칙 + 점수(0-100) + 상세 분석 |
| `sinsal` | 신살 | Pro | 귀인 21종, 살 17종, 12신살 — 기둥별 상세 + 해석 |
| `relationships` | 합형충파해 | Pro | 원국(허자 미적용) + 허자 포함 이중 분석. 삼합/반합 자동 분류 |
| `ghostElements` | 허자 분석 | Pro | 삼합공협·도충 허자의 출투, 진허/가허, 순수성, 강도 |
| `gyeokguk` | 격국 분석 | Pro | 정격 8격 + 외격(종격) + 건록/양인격, 신강/신약 점수 |
| `yongsin` | 용신 분석 | Pro | 억부용신 + 조후용신(궁통보감) + 5신(용희기구한) 파생 |
| `weolun` | 월률분야 | Pro | 절기 기반 지장간 사령(司令) 추출 — 격국·용신 판별의 결정적 기초 데이터. 단순 월 운세가 아닌 명리학 정통 분석 |
| `seun` | 세운 | Pro | 과거/현재/미래 년운 + 합형충파해 관계 + 12운성 |
| `wongukInteraction` | 원국 상호작용 | Pro | 4기둥 간 합형충파해 + 인접/격각 구분 |
| `dailyInteraction` | 일진 상호작용 | Pro | 특정 날짜 일진이 원국에 미치는 작용 — 일진 신살, 4기둥과의 합형충파해, 오행 변화 |
| `evaluation` | 종합 사주 평가 | Pro | 스코어카드·성격·인생흐름·년운·용신가이드 — 전체 모듈 교차 종합 |

## 요청 한도

| 플랜 | 월 호출 | 분당 호출 |
| --- | --- | --- |
| Free | 500회 | 10회 |
| Pro | 10,000회 | 30회 |

응답 헤더 `X-RateLimit-Limit` · `X-RateLimit-Remaining` · `X-RateLimit-Reset`(Unix 초) 으로 잔여량을 확인합니다.
분당 한도를 넘기면 `429 RATE_LIMIT_EXCEEDED` 이며, `X-RateLimit-Reset` 이후 재시도하면 됩니다.

## 도메인 화이트리스트 (CORS)

`Origin` 헤더가 없는 요청(서버 사이드 호출)은 항상 통과합니다.
브라우저에서 직접 호출해야 한다면 키에 허용 도메인을 **먼저 등록**하세요(Pro 키 전용).
등록하면 그 순간부터 등록 도메인 외의 브라우저 호출이 `403 ORIGIN_NOT_ALLOWED` 로 차단됩니다.
등록 전에는 이 차단이 적용되지 않으므로, 키가 브라우저에 노출되는 구성이라면 등록을 마친 뒤 배포하세요.

## 에러 코드

모든 에러 응답은 동일한 구조입니다.

```json
{
  "success": false,
  "error": {
    "code": "KEY_REVOKED",
    "message": "This API key has been revoked. Generate a new key at https://www.sazu.app/manse-api/dashboard/keys"
  }
}
```

| HTTP | code | 설명 및 조치 |
| --- | --- | --- |
| 400 | `VALIDATION_ERROR` | 요청 바디의 파라미터가 잘못되었습니다. `error.details` 에서 누락·타입 오류 필드를 확인하세요. |
| 400 | `SAMPLE_PROFILE_REQUIRED` | Free(샌드박스) 키로 **샘플 프로필과 다른 생년월일**을 요청했습니다. 문서의 샘플 프로필 5종의 입력값과 정확히 일치해야 응답합니다. 응답의 `error.details.sampleProfiles` 에 전체 목록이 함께 반환되므로 코드에서 바로 참조하실 수 있습니다. 실제 생년월일 계산은 Pro 에서 제공됩니다. |
| 401 | `MISSING_API_KEY` | 인증 헤더가 누락되었습니다. `x-api-key` 또는 `Authorization: Bearer <키>` 헤더 중 하나를 포함해야 합니다. 헤더 이름의 대소문자는 무관하지만 철자는 정확히 일치해야 합니다. |
| 401 | `INVALID_API_KEY` | API 키가 존재하지 않습니다. 헤더 값(`x-api-key` 또는 `Authorization: Bearer`)이 대시보드의 키와 일치하는지 확인하세요. |
| 401 | `KEY_REVOKED` | 키가 폐기(revoke)되었습니다. 대시보드에서 새 키를 발급한 뒤 코드에 반영하세요. https://www.sazu.app/manse-api/dashboard/keys |
| 401 | `KEY_EXPIRED` | 키의 만료일이 지났습니다. 대시보드에서 만료일을 갱신하거나 새 키를 발급하세요. |
| 403 | `ORIGIN_NOT_ALLOWED` | 요청 `Origin` 헤더가 키의 허용 도메인에 등록되지 않았습니다. Pro 키의 경우 대시보드 → API 키 → "도메인" 버튼에서 호출할 도메인을 등록하세요. 서버 사이드(Origin 헤더 없음) 호출은 등록 여부와 무관하게 통과합니다. |
| 429 | `RATE_LIMIT_EXCEEDED` | 분당 요청 한도를 초과했습니다. `X-RateLimit-Reset` 헤더의 Unix 타임스탬프 이후 재시도하세요. |
| 503 | `AUTH_UNAVAILABLE` | 인증 서비스에 일시적 장애가 발생했습니다. 잠시 후 재시도하세요. 반복될 경우 문의해 주세요. contact@sazu.app |
| 503 | `QUOTA_UNAVAILABLE` | 사용량 집계 서비스에 일시적 장애가 발생했습니다. 잠시 후 재시도하세요. |
| 500 | `INTERNAL_ERROR` | 서버 내부 오류입니다. 동일한 요청이 반복 실패하면 문의해 주세요. contact@sazu.app |

## 자주 묻는 질문

### SAZU 사주 API 는 무엇을 반환하나요?

생년월일·출생시간·성별을 보내면 사주 원국(연·월·일·시주), 대운, 오행 분포, 신강/신약, 신살, 합형충파해, 격국, 용신, 세운 등 15개 분석 모듈을 JSON 으로 돌려줍니다. 엔드포인트는 `POST https://api.sazu.app/v1/sazu/calculate` 하나이고, `modules` 배열로 필요한 모듈만 골라 응답 크기를 줄일 수 있습니다.

### API 키는 어떻게 발급하나요?

이메일로 회원가입한 뒤 대시보드(https://www.sazu.app/manse-api/dashboard/keys)에서 발급합니다. 신용카드는 필요하지 않습니다. 전체 키 값은 발급 직후 한 번만 표시되므로 즉시 서버 환경변수나 비밀 저장소에 보관하세요. 발급 시 만료 기간도 함께 정합니다.

### 무료로 쓸 수 있나요? Free 플랜의 제한은 무엇인가요?

Free 플랜은 월 500회·분당 10회까지 무료이며 신용카드가 필요 없습니다. 다만 Free 는 샌드박스로 동작해 문서에 공개된 샘플 프로필 5종에 대해서만 응답합니다. 응답 구조·모듈 15종·응답시간은 Pro 와 같으므로 연동과 화면 검증은 그대로 할 수 있고, 실제 생년월일 계산이 필요하면 Pro 로 전환합니다.

### 400 SAMPLE_PROFILE_REQUIRED 오류는 왜 나오나요?

Free(샌드박스) 키로 샘플 프로필에 없는 생년월일을 요청했기 때문입니다. 코드 오류가 아니라 Free 플랜의 정상 동작입니다. 문서의 샘플 프로필 5종 중 하나와 입력값이 정확히 일치해야 응답하며(예: 1998-05-19 10:00 · 남 · 서울), 오류 응답의 `error.details.sampleProfiles` 에 전체 목록이 함께 반환되므로 코드에서 바로 참조할 수 있습니다. 임의의 생년월일을 계산하려면 Pro 플랜이 필요합니다.

### 403 ORIGIN_NOT_ALLOWED 는 어떻게 해결하나요?

키에 허용 도메인이 등록되어 있는데 요청 `Origin` 이 그 목록에 없을 때 나옵니다. 대시보드 → API 키 → "도메인" 에서 호출할 주소를 등록하세요(프로토콜과 호스트까지, 경로는 제외). 허용 도메인 등록은 Pro 키 전용이며, 서버 사이드 호출은 `Origin` 헤더가 없으므로 등록 여부와 무관하게 통과합니다.

### 브라우저에서 API 를 직접 호출해도 되나요?

권장하지 않습니다. 브라우저에서 호출하면 API 키가 화면 소스에 그대로 노출되어 누구나 복사해 사용량을 소진할 수 있습니다. 자체 백엔드에서 호출하고 결과만 화면으로 내려보내는 구조가 안전합니다. 정적 사이트처럼 백엔드를 둘 수 없다면 Pro 키에 허용 도메인을 등록해 도용 범위를 제한하세요.

### 음력 생일은 어떻게 보내나요?

`isLunar: true` 로 보내면 음력으로 해석합니다. 윤달 출생이면 `isLeapMonth: true` 를 함께 보내야 합니다 — 윤달이 드는 해에는 같은 달이 두 번 오므로 연·월·일만으로는 양력 하루가 정해지지 않고, 평달과 윤달은 약 29일 차이라 월주·일주·시주가 모두 달라집니다.

### 출생 시간을 모르면 어떻게 하나요?

`birthHour` 를 `null` 로 보내면 시주 없이 계산합니다. 응답의 시주 자리는 `null` 로 내려오므로 화면에서 빈 기둥을 처리하면 됩니다. 시주가 빠지면 신강·신약 판정과 신살 일부가 달라질 수 있습니다.

### 진태양시(眞太陽時)는 어떻게 적용하나요?

`trueSolarTime: true` 를 보내면 출생지 경도와 균시차를 반영해 시각을 보정합니다. `birthCity` 로 도시를 지정하면 그 도시의 경도가 쓰이며, 생략하면 서울 기준입니다. 경계 시각(예: 자시·오시 근처) 출생이면 이 옵션 하나로 시주가 바뀔 수 있습니다.

### 요청 한도를 넘기면 어떻게 되나요?

분당 한도를 넘기면 `429 RATE_LIMIT_EXCEEDED` 가 반환됩니다. 응답 헤더 `X-RateLimit-Reset` 의 Unix 타임스탬프 이후 재시도하면 되고, `X-RateLimit-Remaining` 으로 남은 횟수를 미리 확인할 수 있습니다.

### Claude Code·Cursor 같은 AI 에이전트에서 바로 쓸 수 있나요?

MCP 서버 `@sazuapp/mcp-server` 를 등록하면 AI 에이전트가 자연어로 사주 분석을 호출합니다(Pro 전용). 서버 코드에서 쓸 때는 공식 TypeScript SDK `@sazuapp/client` 를 `npm install` 해 세 줄이면 연동됩니다(전 플랜 사용 가능).

## 도구

- OpenAPI 3.1 스펙(공개 엔드포인트): https://www.sazu.app/manse-api/openapi.json
- 공식 TypeScript SDK: `npm install @sazuapp/client` (전 플랜)
- AI 에이전트용 MCP 서버: `npx -y @sazuapp/mcp-server` (Pro 전용)
- 요금제: https://www.sazu.app/manse-api/pricing

---

본 문서는 SAZU(운영: Inavan)가 발행하며 https://www.sazu.app/manse-api/docs 가 원본입니다. 인용 시 원본 주소를 함께 표기해 주세요.
