edutap.ai developers

API 레퍼런스

Mooni 챗 직접 호출 HTTP API

대부분의 통합은 <mooni-frame> Web Component로 충분하며, 이 엔드포인트들은 내부적으로 호출됩니다. 서버 사이드나 커스텀 클라이언트 통합이 필요할 때만 이 페이지를 참고하세요.

Base URL

환경Base URL
프로덕션https://ax-cs-demo.vercel.app
스테이징https://ax-cs-demo.vercel.app

인증

모든 엔드포인트는 mooni-api-key 헤더가 필요합니다:

mooni-api-key: mooni_your_api_key_here

서버는 키의 SHA-256 해시를 테넌트 설정과 비교합니다. Origin도 테넌트 화이트리스트와 검증합니다.

POST /api/chat

챗 응답을 Server-Sent Events로 스트리밍합니다.

요청

POST /api/chat
Content-Type: application/json
mooni-api-key: mooni_xxx
{
  "query": "비밀번호는 어떻게 재설정하나요?",
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "userId": "user@example.com",
  "brandId": "school-a"
}
필드타입필수설명
querystring사용자 질문. trim됩니다. 최대 500자.
sessionIdstringoptional대화 식별자 (UUID 권장). 어드민 기록을 위해 필요.
userIdstring | nulloptional호스트 사이트 유저 ID. null/없음 → 익명 세션.
brandIdstringoptional브랜드별 FAQ 검색 필터.

응답 (Server-Sent Events)

Content-Type: text/event-stream. 이벤트는 data: 라인의 JSON이며 data: [DONE]으로 종료됩니다.

type페이로드발생 시점
status{ status: "searching", level: "loading" }검색 시작
status{ status: "out_of_scope", level: "warning" }점수가 임계값 미만 (적절한 매칭 없음)
text{ content: "..." }답변 청크 (~3단어 단위, ~18ms 간격)
faq{ results: [...] }관련 FAQ 추천 (있는 경우)
status{ status: "done", level: "success" }스트림 완료
error{ message: "search_failed" }서버 에러 ([DONE] 따라옴)

스트림 예시:

data: {"type":"status","status":"searching","level":"loading"}

data: {"type":"text","content":"비밀번호 재설정은 "}

data: {"type":"text","content":"설정 → 계정 → "}

data: {"type":"text","content":"재설정 메뉴에서 가능합니다."}

data: {"type":"faq","results":[{"id":"faq_1","title":"비밀번호 복구"}]}

data: {"type":"status","status":"done","level":"success"}

data: [DONE]

에러

상태본문원인
400{"error":"invalid_json"}본문이 유효한 JSON이 아님
400{"error":"missing_query"}query가 비었거나 string이 아님
400{"error":"query_too_long","maxLength":500}query가 500자 초과
401mooni-api-key 누락 또는 무효
403요청 Origin이 테넌트 화이트리스트에 없음

GET /api/config

테넌트 공개 설정 (표시 이름, 기본 테마, 지원 언어 등)을 반환합니다. iframe 앱이 부팅 시 호출합니다.

GET /api/config
mooni-api-key: mooni_xxx

응답 형태는 테넌트 설정의 공개 영역을 반영합니다. 스키마는 내부 구현이므로 운영 로직에서 직접 의존하지 말고 Web Component를 사용하세요.

Rate Limit

기본: API 키당 분당 60 요청. 프로덕션 테넌트의 한도 상향이 필요하면 문의주세요.

데이터 영속화 노트

  • 세션과 메시지는 sessionId가 제공된 경우에만 영속화됩니다. sessionId 없는 레거시 임베드는 어드민 기록 자체가 생성되지 않습니다.
  • 사용자 레코드는 userId가 non-null일 때만 어드민에 생성됩니다.
  • 영속화는 fire-and-forget으로 동작하며, 쓰기 실패는 로깅되지만 챗 응답에는 영향을 주지 않습니다.