씰로

SEALO API 문서

PHASE 0 · UNSTABLE
v0.2 · 2026-09-02

SEALO의 서버 API는 AI 초안을 사용자 본인의 말투로 다시 쓰기 위한 말투 추출·다시 쓰기·프로필 저장·계측 4종으로 구성됩니다. 아래는 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/profile POST /api/track 공통 사항

Base URL

https://sealo-site.vercel.app # sealo.kr DNS 연결 전 임시 도메인 — 연결 후 https://sealo.kr로 교체됩니다

모든 요청·응답 본문은 application/json이며, 요청은 전부 POST만 허용합니다. 그 외 메서드는 405를 반환합니다.

말투 추출

POST/api/style-extract

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

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

요청 본문

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

요청 예시

curl -sS -X POST https://sealo-site.vercel.app/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-extractrules에 번호(id)를 붙여 보냅니다
mode"personal"|"org"선택기본 personal. org는 수치·비교·전망 문장을 빈칸 판정

요청 예시

curl -sS -X POST https://sealo-site.vercel.app/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새 숫자가 생겨 원문으로 되돌린 문장 수(생성 금지 게이트)
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[]필수이미 다시 쓴 최종 문장 목록. 합쳐서 10,000자 이하

응답 (200)

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

에러

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

프로필 저장 내부용

POST/api/profileWEBAPP INTERNAL

사용자가 확정한 말투 항목을 프로필로 저장합니다. 원문은 저장하지 않습니다materials에는 재료 출처와 글자 수만 남습니다(확정 9). 소유권 인증이 없는 익명 세션 모델이라 외부 통합용이 아니라 SEALO 웹앱 전용으로 설계됐습니다. 현재 미리보기 화면(/voice)은 이 API를 호출하지 않습니다 — 저장은 대기목록 이후 실서비스에서만.

요청 본문

필드타입필수설명
rulesArray<{rule, why?, evidence?}>필수1~20개. rule이 빈 문자열인 항목은 제외됩니다
asset_source"paste"|"blog"|"kakao"선택재료 출처(확정 10 · P1 재료 3종). 기본값 paste
char_countnumber선택재료 글자 수(원문 대신 저장되는 메타)
anonstring선택익명 세션 ID(최대 64자) — 클라이언트가 로컬에서 생성해 재사용

응답 (200)

{ "profile_id": "uuid", "rules": 4 }

에러

상태사유
400유효한 rule이 1개 미만이거나 20개 초과
502저장 실패 — 확정 내용은 클라이언트(브라우저)에 남아 있으므로 재시도 가능
503저장소 미연결(서버 설정 문제)

계측 수집 내부용

POST/api/trackWEBAPP INTERNAL

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

허용 이벤트

profile_created · taste_rule_edited · draft_submitted · transform_done · published_as_is · revision_loop

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

요청 본문

필드타입필수설명
evstring필수위 허용 이벤트 중 하나. 목록 밖 값은 400
anonstring선택익명 세션 ID(최대 64자)
propsobject선택이벤트 부가 속성(자유 형식 JSON)

응답

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

공통 사항

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

SEALO(씰로) API 문서 v0.2 · 갱신 2026-09-02 · Phase 0 기준 — 정식 버전 아님, 예고 없이 바뀔 수 있습니다.
문의: ilgam.jtbd@gmail.com