URL 규칙과 무료 엔드포인트
일반적인 요청에 404가 나온다면 십중팔구 접두사가 틀렸거나 비표준 경로에서 Swagger UI를 찾고 있는 경우입니다. 이 페이지는 모든 표준 URL과 별칭을 정리합니다.
경로 접두사
섹션 제목: “경로 접두사”모든 엔드포인트는 /v1/ 아래에 있습니다. 다른 접두사는 없습니다.
✅ https://api.astroway.info/v1/chart✅ https://api.astroway.info/v1/health❌ https://api.astroway.info/api/chart - 404 (missing /v1/ prefix)❌ https://api.astroway.info/api/v1/chart - 404 (our internal path, not exposed)❌ https://api.astroway.info/v1/v1/chart - 308 redirect to /v1/chart (typical SDK base-URL bug fix)실수로 /api/<endpoint>를 사용하면 error.code = "WRONG_PREFIX" 필드와 힌트가 담긴 404를 반환합니다. SDK가 이를 처리해 올바른 경로를 안내할 수 있습니다.
LLM 프록시가 아닙니다
섹션 제목: “LLM 프록시가 아닙니다”AstroWay는 점성술 계산 API이지 LLM용 proxy가 아닙니다. OpenAI SDK에 익숙한 습관대로 base_url만 저희 주소로 바꾸면 작동하지 않습니다:
❌ POST /v1/chat/completions - doesn't exist❌ POST /v1/completions - doesn't exist❌ GET /v1/models - doesn't exist (deliberately)❌ POST /v1/embeddings - doesn't existAI 제공업체 목록은 두 가지 이유로 공개하지 않습니다:
- 통합하는 쪽에서 활용할 수 없습니다. 여러분은
/v1/interpret/natal이나/v1/horoscope/daily를 호출하고, 저희 서버가 자동 fallback을 갖춘 여러 제공업체 중에서 LLM을 직접 고릅니다. 제공업체가 바뀌어도 응답의 shape는 바뀌지 않으며, latency와 가끔의 문구 차이만 달라집니다. - 운영상의 자유. 체인은 예고 없이 바뀝니다(2026-05-18 HuggingFace 제외, NIM/ZAI 추가). 특정
models[]를 공표하면 그것이 사실상 계약이 되어 버립니다.
AI는 구현 세부 사항으로만 존재합니다: /v1/interpret/*(출생 차트, 시나스트리, 트랜짓), /v1/horoscope/*(일간/주간 운세), /v1/dev-assistant(문서 도우미), /v1/reports/*(PDF 내러티브). 나머지 750개 이상의 엔드포인트는 AI 없는 결정적 Swiss Ephemeris입니다.
OpenAPI 3.1 명세
섹션 제목: “OpenAPI 3.1 명세”표준 주소는 **/v1/openapi.json**입니다. 통합 편의를 위해 별칭을 추가했습니다:
| 별칭 | 대상 | 존재 이유 |
|---|---|---|
/v1/swagger.json | 301 → /v1/openapi.json | Swagger 2.0 / openapi-generator convention |
/v1/api-docs/swagger.json | 301 → /v1/openapi.json | springdoc default |
/v1/v3/api-docs | 301 → /v1/openapi.json | Spring Boot 3 |
/v1/v2/api-docs | 301 → /v1/openapi.json | Spring Boot 2 |
/v1/swagger/v1/swagger.json | 301 → /v1/openapi.json | ASP.NET Core |
/v1/swagger, /v1/swagger-ui, /v1/swagger-ui.html | 302 → /v1/docs | Swagger UI 호스트 |
대화형 Swagger UI는 /v1/docs에서 사용할 수 있습니다(브라우저 문서 /docs/api/에도 미러링되어 있습니다).
무료 시스템 엔드포인트
섹션 제목: “무료 시스템 엔드포인트”이 경로들은 API 키가 필요 없고 크레딧을 차감하지 않습니다. 어떤 프론트엔드, 모니터링, health-check에서든 호출할 수 있습니다.
| 경로 | 반환값 |
|---|---|
GET /v1/health | {status, version, uptime_seconds, timestamp}: 빠른 liveness probe |
GET /v1/health/deep | DB별 연결 확인(UptimeRobot / Pingdom용), DB가 하나라도 불가하면 503 |
GET /v1/version | {version, build_commit, started_at, uptime_seconds, docs_url}: SDK용 상세 self-check |
GET /v1/openapi.json | 예제와 x-codeSamples가 포함된 전체 OpenAPI 3.1 명세 |
GET /v1/docs | 대화형 Swagger UI |
GET /v1/reference/* | 표준 참조 데이터(사인, 행성, 하우스, 애스펙트), IP rate limit, 키 불필요 |
GET /v1/i18n/langs, GET /v1/i18n/dict/:lang | 언어 목록과 UI 사전, 위젯용 |
가입이 필요한 무료 endpoints
섹션 제목: “가입이 필요한 무료 endpoints”계정 엔드포인트는 JWT 토큰으로만(로그인 시 발급) 사용할 수 있지만 플랜 잔액에서 크레딧을 차감하지 않습니다.
| 접두사 | 설명 |
|---|---|
/v1/auth/* | 가입, 로그인, refresh, password reset |
/v1/me, /v1/me/* | 프로필, 통계, recent calls |
/v1/keys, /v1/keys/* | API 키 관리 |
/v1/admin/* | 관리자 패널(api_role = admin 필요) |
/v1/messages | 위젯에서 보내는 피드백(익명, rate limit) |
/v1/dev-assistant, /v1/dev-assistant/stream | 문서용 AI 도우미(익명, 별도 한도) |
/v1/widget-config | 위젯용 런타임 feature flag |
/v1/embed/* | 임베드 가능한 iframe 위젯(IP rate limit) |
/v1/oauth/* | Google / GitHub 로그인 |
/v1/books/* | Birth Book, 별도 scope JWT(WordPress mu-plugin이 발급) |
유료 계산 엔드포인트
섹션 제목: “유료 계산 엔드포인트”모든 점성술 계산은 요금제에서 크레딧을 차감합니다. 각 엔드포인트의 정확한 비용은 엔드포인트 비용 페이지에 있습니다. 요약:
| Tier | 크레딧 | 예시 |
|---|---|---|
| 0 | 0 | /v1/reference/*: 공개 참조 데이터, 키 불필요 |
| ½ | 5 | /v1/kabbalah/sephiroth, /v1/fixed-stars/catalog: 정적 테이블 |
| 1 | 10 | /v1/planets, /v1/sun-times, /v1/moon-phase |
| 2 | 20 | /v1/chart, /v1/harmonics, /v1/horary |
| 3 | 50 | /v1/synastry, /v1/progressions, /v1/acg |
| 4 | 100 | /v1/transit-calendar, /v1/group-synastry |
| 5 | 250 | /v1/rectification/trutine, AI 내러티브 /v1/reports/ai/* |
| 6 | 500 | /v1/rectification |
| 7 | 5000 | PDF 리포트: /v1/reports/natal, /v1/reports/synastry |
캐시 할인: X-Cache: HIT(5분 idempotency 캐시)는 0 크레딧입니다. AI 엔드포인트(/interpret/*)는 cache hit 시 50% 할인됩니다.
응답 헤더에는 X-Credits-Used, X-Credits-Remaining, X-Credits-Limit이 포함되어 SDK가 잔액을 자동으로 추적할 수 있습니다.
응답 언어
섹션 제목: “응답 언어”언어는 ?lang= 또는 Accept-Language 헤더로 지정합니다. 21개 언어를 지원합니다.
닫힌 집합의 필드(사인, 행성, 요일, 달의 위상, Human Design 용어, 타로 메이저 아르카나 이름)는 두 번 반환됩니다. 영어 식별자는 안정적인 계약으로서 제자리에 남고, 그 옆에 번역이 담긴 localized 객체가 옵니다:
{ "phaseName": "Waxing Gibbous", "moonSign": "Capricorn", "localized": { "phaseName": "Zunehmender Mond", "moonSign": "Steinbock", "sunSign": "Löwe" }}비교는 영어 값으로 하고, 표시는 localized로 하세요. 이 이름들은 기계 번역이 아니라 코드에 있는 명시적인 용어 테이블에서 가져옵니다. 전문 용어는 단어 단위로 번역할 수 없습니다. 그렇게 하면 달의 위상이 금융 용어로 바뀌어 버립니다.
Human Design에서 localized.centers의 센터는 centers[].name과 같은 식별자를 키로 가지므로, 매칭은 번역된 문자열이 아니라 키로 합니다. 타로에서는 localized.cards가 같은 역할을 하며 키는 카드의 slug입니다.
열린 집합의 필드는 아직 영어이며 그렇게 문서화되어 있습니다: 오늘의 행성의 themes[], 타로 카드의 키워드와 의미, Human Design 채널과 게이트 이름. 마이너 아르카나 이름은 고정된 계급과 수트 형태로 조합되므로 78장 덱 전체가 현지화되어 있고 nameLocalized는 true입니다. 이 필드는 테이블이 이름을 제공할 수 없는 곳에서만 false로 남습니다. 열린 집합은 여러분 쪽에서 번역하거나 별도 사전을 기다리세요.
간결한 응답: fields와 precision
섹션 제목: “간결한 응답: fields와 precision”에이전트는 읽는 토큰마다 비용을 냅니다. POST /v1/chart는 약 32 KB를 반환하지만 모델에게는 보통 그중 두 열만 필요하고, 각 황경은 누구도 각분(arcminute)보다 정밀하게 작업하지 않는 곳에서 소수점 이하 14자리로 옵니다.
두 쿼리 파라미터가 마지막 단계에서 이 문제를 해결하므로 모든 엔드포인트에서 작동합니다:
fields:data기준 상대 경로를 쉼표로 구분한 목록입니다. 경로는 배열의 각 요소에 적용되므로planets.name은 배열의 키가 아니라 각 행성의 이름을 뜻합니다.precision: 0에서 15 사이의 정수로, 응답의 모든 비정수 숫자를 반올림합니다. 정수는 건드리지 않습니다. 식별자는 측정값이 아니기 때문입니다.
curl -X POST "https://api.astroway.info/v1/chart?fields=planets.name,planets.longitude&precision=2" \ -H "X-Api-Key: aw_live_..." -H "Content-Type: application/json" \ -d '{"date":"1990-05-15","time":"14:30:00","timezone":"Europe/Kyiv","latitude":50.45,"longitude":30.52}'출생 차트에서 이 두 파라미터를 쓰면 32 410바이트 대신 511바이트, 즉 응답이 60분의 1로 줄어듭니다.
아무것도 찾지 못한 경로는 조용히 사라지지 않습니다. 응답 옆의 _fields_unmatched 필드에 담겨 옵니다. 일부 필드는 실제로 선택 사항이어서 특정 응답에 없을 수 있으므로 이는 오류가 아닙니다. 하지만 어떤 경로도 일치하지 않는 목록은 오타이며, 목록과 함께 400 FIELDS_UNKNOWN을 반환합니다. 차트 대신 빈 객체를 주는 것은 자신만만하게 틀린 응답이 될 것입니다.
두 파라미터는 헤더가 아니라 query로 전달되며, 이는 의도된 것입니다. 응답 캐시의 키는 메서드, 경로, 본문, 정렬된 query, 플랜으로 구성됩니다. 헤더로 모드를 지정하면 2026-08-22의 사고가 되풀이될 것입니다. 그때 Accept-Language가 키에 포함되지 않아 독일어 응답이 다음 요청자에게 우크라이나어 응답으로 전달되었습니다.
셰이핑은 data에만 적용됩니다. 봉투, _footer, _warning은 그대로 유지됩니다.
MCP에서도 똑같이 작동합니다. mcp.astroway.info의 모든 도구는 자체 파라미터와 함께 fields와 precision을 받아 같은 query로 API에 넘깁니다. MCP를 통한 출생 차트는 91 737바이트였습니다. 데이터가 들여쓰기된 텍스트 블록과 구조화된 필드로 두 번 왔기 때문입니다. 같은 세 경로와 precision: 2를 쓰면 1 182바이트입니다.
| 출생 차트 호출 | 바이트 |
|---|---|
| MCP, 21.09.2026 이전 방식 | 91 737 |
| MCP, 텍스트 블록 들여쓰기 없음 | 72 484 |
MCP, precision: 2 | 61 356 |
MCP, fields에 세 경로와 precision: 2 | 1 182 |
REST, fields에 세 경로와 precision=2 | 559 |
출생 시간을 모르는 경우
섹션 제목: “출생 시간을 모르는 경우”최종 사용자 중 상당수는 정확한 출생 시간을 모릅니다. 임의로 정오를 넣고 평소처럼 차트를 계산하면, 응답에 그럴듯해 보이지만 오차 2시간마다 대략 사인 하나씩 틀리는 어센던트와 하우스 커스프가 나타납니다.
그래서 time 대신 timeUnknown: true를 전달할 수 있습니다:
curl -X POST https://api.astroway.info/v1/chart \ -H "X-Api-Key: aw_live_..." \ -H "Content-Type: application/json" \ -d '{"date":"1990-03-15","timeUnknown":true,"timezoneOffset":2,"latitude":50.45,"longitude":30.52}'이 모드에서 API가 반환하는 것:
| 필드 | 값 |
|---|---|
planets | 현지 정오 기준으로 계산됨 |
aspects | 계산되지만 달과의 애스펙트는 신뢰할 수 없음(아래 참조) |
houses | null |
houseAspects | null |
chartSect | null |
siderealTime | null |
timeUnknown | 무엇이 생략되었고 달이 어디에 있을 수 있는지 설명하는 블록 |
timeUnknown.moon 블록에는 하루의 시작과 끝 시점의 달 황경, 하루 동안 지나간 호(11.8-15.4°), 달이 머문 사인 목록, 그리고 changesSign 플래그가 담깁니다. 달은 하루 사이에 사인을 바꿀 수 있으므로 이 범위를 숫자 하나로 감추지 말고 사용자에게 보여 주는 것이 좋습니다.
이 플래그는 /v1/chart와 /v1/synastry가 받습니다(시나스트리에서는 파트너별로 따로 설정할 수 있습니다). 나머지 엔드포인트는 하우스나 앵글에 의존하므로 400 TIME_UNKNOWN_UNSUPPORTED로 응답합니다. 플래그를 조용히 무시하고 지어낸 어센던트를 응답에 넣는 것보다 명시적인 오류가 낫습니다.
API 버전 관리
섹션 제목: “API 버전 관리”메이저 버전은 URL(/v1/)에 있습니다. Breaking change는 in-place가 아니라 /v2/에서만 이루어집니다. 자세한 내용: 버전 관리.
GET /v1/version은 현재 배포를 반환합니다:
curl https://api.astroway.info/v1/version# {# "version": "2.71.0",# "build_commit": "abc1234",# "started_at": "2026-05-27T10:42:00Z",# "uptime_seconds": 12345,# "docs_url": "https://api.astroway.info/docs/api/"# }SDK는 “왜 갑자기 동작이 달라졌는지” 디버깅하기 위해 시작할 때 이를 호출할 수 있습니다. build_commit 필드가 배포를 정확히 식별합니다.
가장 자주 보는 잘못된 호출
섹션 제목: “가장 자주 보는 잘못된 호출”90일간의 프로덕션 로그 분석에서 나온 대표적인 통합 오류 5가지:
/v1/<endpoint>대신/api/<endpoint>: WordPress wp-json에서 온 습관입니다. 이제 hint가 담긴 JSON 404를 반환합니다./v1/v1/<endpoint>: SDK가baseUrl = .../v1로 설정된 상태에서 그 위에/v1/X를 덧붙입니다. 이제 308 redirect입니다./v1/openapi.json대신/swagger.json: Postman/Insomnia의 자동 탐색입니다. 이제 301 redirect입니다.Authorization: Bearer <jwt>없는/v1/me,/v1/auth/keys/me→ 401. 토큰이 헤더로 전달되는지 확인하세요.- embed 토큰 대신 API 키를 쓴
/v1/embed/natal→ 401. Embed 엔드포인트는 API 키가 아니라 dashboard의 공개 embed-token을 받습니다.
관련 항목
섹션 제목: “관련 항목”- 빠른 시작: 5분 안에 첫 요청
- 인증: JWT, API 키, embed 토큰
- 엔드포인트 비용: 정확한 크레딧 표
- 오류: error codes 목록
- OpenAPI 3.1: 전체 명세