SEALO

SEALO API 문서

PHASE 0 · UNSTABLE
v0.3 · 2026-09-06

SEALO의 서버 API는 AI 초안을 사용자 본인의 말투로 다시 쓰기 위한 말투 추출·다시 쓰기·리포트·계측과, 운영자 전용 지표 조회로 구성됩니다. 아래 목차가 전부입니다. 아래는 Phase 0 단계의 API 레퍼런스입니다 — 정식 v1은 아니며 사전 통지 없이 바뀔 수 있습니다.

인증은 아직 없고, IP당 일일 호출 수 제한만 있습니다. 이 문서의 엔드포인트는 SEALO 웹앱(/voice)이 같은 출처에서 호출하도록 만들어졌습니다. /api/style-extract·/api/rewrite는 호출마다 모델 API 비용이 발생하며, IP당 하루 호출 수를 넘으면 429를 반환합니다(정확한 한도는 비공개 — 어뷰징 방지). 대량·자동화 연동을 계획 중이라면 먼저 ilgam.jtbd@gmail.com로 문의해 주세요 — 사전 협의 없는 대량 호출은 예고 없이 차단될 수 있습니다.
Base URL POST /api/style-extract POST /api/rewrite POST /api/report POST /api/track GET /api/kpi 공통 사항

Base URL

https://sealo.kr

모든 요청·응답 본문은 application/json입니다. /api/kpi를 뺀 나머지는 POST만 받고, /api/kpi는 GET만 받습니다. 그 외 메서드는 405를 반환합니다.

말투 추출

POST/api/style-extract

사용자가 직접 쓴 한국어 글에서 말투(관찰·말투 항목 후보·안 쓰는 표현)를 추출합니다. 모든 관찰·항목에는 입력 원문에서 그대로 복사한 근거 인용이 붙고, 근거가 원문에 실재하지 않으면 서버가 해당 항목을 드롭합니다(생성 금지 게이트) — 응답의 dropped가 그 개수입니다.

내부적으로 복수의 추출 엔진을 정해진 순서로 시도하고, 앞선 엔진이 실패(미설정·오류·응답 파싱 실패)하면 다음으로 넘어갑니다. 생성 금지 게이트는 어느 엔진이 응답했든 동일하게 적용되므로 응답 형식과 생성 금지 게이트는 엔진에 무관하게 동일합니다 — 어느 엔진이 실제로 응답했는지는 클라이언트에 노출하지 않습니다.

요청 본문

필드타입필수설명
textstring필수분석할 원문. 80자 이상 20,000자 이하. 원문은 저장되지 않습니다.

요청 예시

curl -sS -X POST https://sealo.kr/api/style-extract \
  -H "Content-Type: application/json" \
  -d '{"text":"여기에 80자 이상의 직접 쓴 글을 넣습니다..."}'

응답 (200)

필드타입설명
observationsArray<{title, evidence}>말투 관찰 3~6개. evidence는 원문 그대로의 인용
rulesArray<{rule, why, evidence}>실행 가능한 말투 항목 후보 2~5개. rule은 15자 이내 한 줄
avoidsArray<{phrase, why}>이 글이 일관되게 피하는 표현 0~5개. 확실하지 않으면 빈 배열
droppednumber근거가 원문에 없어 드롭된 항목 수(생성 금지 게이트 작동 확인용)

응답 예시

{
  "observations": [
    { "title": "한 문장에 한 가지 사실만 담아 짧게 끊어 씀",
      "evidence": "그래서 매번 처음부터 다시 씁니다." }
  ],
  "rules": [
    { "rule": "문장은 짧게 끊는다",
      "why": "글 전체가 단문 위주로 구성되어 있고, 본인이 그 습관을 명시적으로 드러낸다",
      "evidence": "문장도 짧게 끊어 쓰는 편인데 AI는 자꾸 길게 늘여 씁니다." }
  ],
  "avoids": [],
  "dropped": 0
}

에러

상태사유
400text가 80자 미만이거나 20,000자 초과
429IP당 일일 호출 수 초과, 또는 상위 API 한도 초과 — 잠시 후·다음 날 재시도
502추출 실패(모델 거부·응답 파싱 실패 등) — 입력을 바꾸지 않고 재시도 가능
503추출 엔진 미연결(서버 설정 문제) — 클라이언트에서 해결 불가

다시 쓰기

POST/api/rewrite

AI 초안을 사용자의 말투 항목으로 문장 단위로 다시 씁니다. 의미·주장·수치는 바꾸지 않고 말투만 바꿉니다. 바뀐 문장에 원문에 없던 숫자가 생기거나, 원문의 숫자가 빠지거나, 원문의 로마자 고유 표기가 사라지면 서버가 그 문장을 원문으로 되돌립니다(생성 금지 게이트, reverted_count). 원문에 없던 제목·목록 기호는 떼고 문장만 돌려줍니다. 조직 모드(mode:"org")에서는 회사 문서가 아직 0건이므로 수치·비교·전망 문장을 blank:true로 표시합니다 — 근거 없으면 비웁니다. 초안·결과는 저장되지 않습니다.

요청 본문

필드타입필수설명
draftstring필수AI 초안. 20자 이상 10,000자 이하
rulesArray<{id, rule, evidence?}>필수1~10개. /api/style-extract의 rules에 번호(id)를 붙여 보냅니다
mode"personal"|"org"선택기본 personal. org는 수치·비교·전망 문장을 빈칸 판정

요청 예시

curl -sS -X POST https://sealo.kr/api/rewrite \
  -H "Content-Type: application/json" \
  -d '{"draft":"저희 팀은 남다른 방식으로 문제를 풉니다. 시장은 앞으로도 계속 성장할 전망입니다.",
       "rules":[{"id":1,"rule":"결론을 첫 문장에 둔다"},{"id":2,"rule":"숫자엔 단위를 붙인다"}],
       "mode":"personal"}'

응답 (200)

필드타입설명
sentencesArray<{original, rewritten, rule_ids, claim, blank, reason?, reverted?}>초안 문장 순서대로. rule_ids는 적용한 항목 번호. claim은 수치·비교·전망 신호. blank는 조직 모드에서 근거 없음
changed_countnumber말투가 바뀐 문장 수
reverted_countnumber숫자·로마자 고유 표기가 달라져 원문으로 되돌린 문장 수(생성 금지 게이트)
changed_rationumber|null엔진이 바꾼 양 — 바뀐 글자 수 ÷ 원문 글자 수(편집거리, 0~1, 소수 셋째 자리). 조직 모드에서 비운 문장은 계산에서 뺍니다. 0이면 바꾼 곳이 없다는 뜻이고 화면은 「내 말투와 다른 곳을 찾지 못했어요」를 띄웁니다. 원문 글자가 없으면 null
org_docsnumber조직 문서 수 — 현재 항상 0
truncatedboolean모델 출력이 max_tokens에서 잘렸을 때 true. 완결된 문장까지만 반환됩니다(화면 v2 P1 §1)

에러

상태사유
400draft 길이 위반 또는 유효한 rules 0개
429IP당 일일 호출 수 초과, 또는 상위 API 한도 초과
502다시 쓰기 실패(모델 거부·응답 파싱 실패, 또는 잘림 후 건질 문장이 0개) — 초안을 바꾸지 않고 재시도 가능
503다시 쓰기 엔진 미연결(서버 설정 문제)

리포트 재배열

POST/api/report

이미 /api/rewrite로 다시 쓴 문장 목록을 5단 리포트 구조(한 줄 결론·핵심 3·본문 소제목·숫자·다음 할 일)로 재배열합니다. 새 내용을 만들지 않습니다 — 입력 문장을 고르고 순서만 바꿉니다. 각 항목은 입력 문장 중 하나를 그대로 인용한 evidence가 있어야 채택되고, 없으면 서버가 드롭합니다(생성 금지 게이트).

요청 본문

필드타입필수설명
sentencesstring[]필수이미 다시 쓴 최종 문장 목록. 앞에서 400개까지만 쓰고 나머지는 잘라냅니다(거부 아님). 그렇게 자른 뒤 합쳐서 12,000자를 넘으면 400

응답 (200)

필드타입설명
conclusionstring한 줄 결론. 원문에 결론 문장이 없으면 빈 문자열
key_pointsArray<{text, evidence}>핵심 최대 3개
sectionsArray<{heading, body}>소제목 단위 본문 재배열. 최대 6개
numbersArray<{value, unit, context, evidence}>입력에 나온 수치만
next_actionsArray<{text, evidence}>입력이 행동을 제안한 경우만. 최대 4개

에러

상태사유
400sentences 0개 또는 합쳐서 12,000자 초과
429IP당 일일 호출 수 초과, 또는 상위 API 한도 초과
502재배열 실패(모델 거부·응답 파싱 실패)
503리포트 엔진 미연결(서버 설정 문제)

계측 수집 내부용

POST/api/trackWEBAPP INTERNAL

화이트리스트에 있는 이벤트만 기록합니다(확정 7 — 계측은 서버 기록이 정본). 전송 실패가 사용자 경험을 막지 않도록 설계돼 있어, 저장소 미연결 시에도 202로 무해 응답합니다. 화면에서는 data-ev 속성 한 개와 위임 리스너 한 개로 발화합니다. published_as_is는 edit_ratio 0(원래대로·직접 쓰기 0건) 상태에서 복사·내보내기 행동이 있을 때만 셉니다 — 되돌리거나 직접 채운 문장이 있으면 복사해도 세지 않습니다.

허용 이벤트

profile_created · taste_rule_edited · draft_submitted · transform_done · published_as_is · revision_loop

미리보기 화면의 profile_created는 stored:false 속성으로 옵니다 — 내 말투가 만들어진 시점이지 저장이 아닙니다. 서버 저장은 실서비스에서만.

transform_done(view:"editor")과 published_as_is는 changed_ratio 속성을 함께 싣습니다 — /api/rewrite가 돌려준 값 그대로입니다. 0~1 숫자나 null만 받고, 그 밖의 값은 키째 버립니다(없는 값을 0으로 세지 않게). 사용자가 게시 전에 고친 양(edit_ratio)과는 다른 값입니다.

taste_rule_edited는 origin 속성으로 어디서 고쳤는지 함께 옵니다 — inline(말투를 꺼낸 뒤 그 자리에서) · tab(「내 말투」에서). 이름은 여섯 가지 그대로이고 속성만 늘렸습니다.

요청 본문

필드타입필수설명
evstring필수위 허용 이벤트 중 하나. 목록 밖 값은 400
anonstring선택익명 세션 ID(최대 64자)
propsobject선택이벤트 부가 속성(자유 형식 JSON). published_as_is.position은 editor · file · summary · body_end 4값만 기록하고, 그 밖의 값은 202 {"stored":false,"reason":"position"}로 무시합니다

응답

상태본문의미
200{"stored":true}저장 성공
202{"stored":false}저장소 미연결 — 무해 응답(클라이언트 재시도 불필요)
400{"error":"..."}허용되지 않은 이벤트
502{"stored":false}저장 실패

지표 조회 운영자용

GET/api/kpiOPERATOR ONLY

운영 화면(/admin)이 지표 한 줄을 읽어 가는 곳입니다. 이 문서의 다른 엔드포인트와 달리 GET만 받고, 열쇠말(ADMIN_TOKEN)이 맞아야 응답합니다. 계산은 전부 저장소 뷰에 있고 이 엔드포인트는 그 값을 그대로 돌려줍니다 — 여기서 숫자를 만들지 않습니다. 값이 null이면 아직 잴 것이 없다는 뜻이며 0.0이 아닙니다.

요청 헤더

헤더타입필수설명
x-admin-tokenstring필수서버에 등록한 열쇠말. 앞뒤 공백은 양쪽 모두 무시합니다

응답 (200)

필드타입설명
kpiobject|null지표 한 행. 합성 트래픽을 뺀 값만 셉니다
measured_atstring잰 시각(ISO 8601)

오류

상태의미
401열쇠말이 오지 않았거나 맞지 않음 — 문장이 둘을 구분해 알려줍니다
405GET 외 메서드
429틀린 시도가 상한을 넘음. 열쇠말을 보내지 않은 요청은 세지 않습니다 — 주소창으로 열어 보는 진단은 상한을 깎지 않습니다
502지표 저장소 조회 실패
503서버에 열쇠말이 등록되지 않았거나 저장소에 연결돼 있지 않음

공통 사항

/api/kpi를 뺀 모든 엔드포인트는 POST만 받고 그 외 메서드에 405를 반환합니다. /api/kpi는 GET만 받습니다. 에러 응답 본문은 {"error": "사람이 읽는 한국어 메시지"} 형식이며, 내부 원인(모델 응답 원문·DB 에러 상세)은 클라이언트에 노출하지 않고 서버 로그에만 남습니다 — 신고 시 요청 시각과 상태 코드를 함께 알려주세요.

SEALO(씰로) API 문서 v0.3 · 갱신 2026-09-30 · Phase 0 기준 — 정식 버전 아님, 예고 없이 바뀔 수 있습니다.
운영 YJ Kim(Founder) · 제이티비디(JTBD) · 문의: ilgam.jtbd@gmail.com · 개인정보처리방침 · 이용약관