GreenTu Law Chat API의 주요 특징과 사용 정보
API Key 없이 URL 호출만으로 바로 사용 가능. CORS 전체 허용으로 모든 도메인에서 접근 가능합니다.
법제처 OpenAPI를 통해 실시간 법령·판례 데이터를 수집하여 AI 답변에 활용. 환각(Hallucination)을 최소화합니다.
실시간 스트리밍(SSE)과 단건 JSON 응답을 모두 지원. 사용 환경에 맞게 선택 가능합니다.
session_id를 통해 이전 대화 맥락을 유지하며 연속 질문이 가능합니다. 최대 30턴 히스토리 관리.
| Method | Endpoint | 설명 | 응답 형식 |
|---|---|---|---|
| POST | /api/chat |
채팅 (SSE 스트리밍) | text/event-stream |
| POST | /api/chat-sync |
채팅 (JSON 단건 응답) | application/json |
| POST | /api/reset |
세션 초기화 | application/json |
| GET | /api/health |
상태 확인 | application/json |
Q. 이 API는 GreenTu 판례 도우미(plain.greentu.io)와 어떤 관계인가요?
A. plain.greentu.io(GreenTu 판례 도우미)와 동일한 법제처 실시간 연동 AI 판례·법령 해설 엔진을 사용합니다. plain.greentu.io는 최종 사용자용 채팅 UI이고, 이 API는 외부 사이트·앱 개발자가 동일 엔진을 자체 서비스에 임베드할 수 있도록 제공하는 공개 개발자 API입니다.
Q. API 사용에 인증이 필요한가요?
A. 인증이 필요 없습니다. API Key 없이 URL 호출만으로 바로 사용 가능하며 CORS가 전체 허용되어 모든 도메인에서 접근할 수 있습니다.
Q. 요청 제한(Rate Limit)이 있나요?
A. IP당 분당 최대 10회 요청으로 제한되며, 초과 시 429 응답(RATE_LIMIT_EXCEEDED)이 반환됩니다.
각 엔드포인트의 상세 사양
보험 손해사정 관련 질문에 대한 AI 답변을 SSE(Server-Sent Events) 스트리밍으로 반환합니다. 실시간 타이핑 효과 구현에 적합합니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
message | string | ✅ | 사용자 질문 내용 |
session_id | string | ❌ | 세션 ID (멀티턴 대화용, 기본값: "default") |
// 답변 텍스트가 조각 단위로 스트리밍됩니다 data: {"type":"content","content":"## [1] 쟁점 정리\n"} data: {"type":"content","content":"후유장해 보험금 청구에서..."} // ... 계속 스트리밍 ... // 완료 시 토큰 사용량 포함 data: {"type":"done","usage":{"prompt":1200,"completion":800,"total":2000}} // 에러 발생 시 data: {"type":"error","error":"에러 메시지"}
SSE 파싱이 어려운 환경(모바일 앱, 서버 to 서버)을 위한 단건 JSON 응답 채팅 엔드포인트입니다. 전체 답변이 완료된 후 한 번에 반환합니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
message | string | ✅ | 사용자 질문 내용 |
session_id | string | ❌ | 세션 ID (기본값: "default") |
{
"status": "ok",
"reply": "## [1] 쟁점 정리\n고지의무 위반 시...",
"usage": {
"prompt": 1200,
"completion": 800,
"total": 2000
},
"session_id": "my_session_123",
"grounding_sources": [
"법제처 법령검색 API",
"법제처 판례검색 API"
]
}지정한 세션의 대화 히스토리를 초기화합니다.
// Request { "session_id": "my_session_123" } // Response { "status": "ok", "message": "세션 'my_session_123'이 초기화되었습니다." }
API 서비스 상태를 확인합니다. 모니터링 및 헬스체크에 사용하세요.
{
"status": "ok",
"service": "GreenTu Law Chat API",
"version": "1.0.0",
"timestamp": "2026-07-13T20:00:00.000Z",
"endpoints": [...]
}| HTTP 상태 | 코드 | 설명 |
|---|---|---|
| 400 | - | message 필드 누락 |
| 405 | - | 허용되지 않는 HTTP Method |
| 429 | RATE_LIMIT_EXCEEDED | 분당 요청 한도 초과 |
| 500 | - | 서버 내부 오류 |
다양한 언어와 환경에서 API를 호출하는 예제
/api/chat)const API_URL = 'https://api.greentu.io/api/chat'; async function sendChat(message, sessionId = 'default') { const response = await fetch(API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, session_id: sessionId }) }); const reader = response.body.getReader(); const decoder = new TextDecoder(); let fullReply = ''; while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value, { stream: true }); for (const line of chunk.split('\n')) { if (!line.startsWith('data: ')) continue; const data = JSON.parse(line.slice(6)); if (data.type === 'content') { fullReply += data.content; console.log(data.content); // 실시간 출력 } else if (data.type === 'done') { console.log('토큰 사용량:', data.usage); } else if (data.type === 'error') { console.error('에러:', data.error); } } } return fullReply; } // 사용 예시 sendChat('후유장해 보험금 청구 기준이 궁금합니다');
import requests import json API_URL = "https://api.greentu.io/api/chat" def send_chat(message, session_id="default"): response = requests.post( API_URL, json={"message": message, "session_id": session_id}, stream=True ) full_reply = "" for line in response.iter_lines(decode_unicode=True): if not line or not line.startswith("data: "): continue data = json.loads(line[6:]) if data["type"] == "content": full_reply += data["content"] print(data["content"], end="", flush=True) elif data["type"] == "done": print(f"\n\n토큰 사용량: {data['usage']}") elif data["type"] == "error": print(f"\n에러: {data['error']}") return full_reply # 사용 예시 send_chat("고지의무 위반 시 보험사 해지권 제척기간은?")
curl -X POST https://api.greentu.io/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "후유장해 보험금 청구 기준", "session_id": "test_001"}'/api/chat-sync)const response = await fetch('https://api.greentu.io/api/chat-sync', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: '자동차보험 손해사정 기준이 궁금합니다', session_id: 'my_session' }) }); const data = await response.json(); console.log(data.reply); // AI 답변 전문 console.log(data.usage); // 토큰 사용량 console.log(data.grounding_sources); // 활용 데이터 소스
import requests response = requests.post( "https://api.greentu.io/api/chat-sync", json={ "message": "자동차보험 손해사정 기준이 궁금합니다", "session_id": "my_session" } ) data = response.json() print(data["reply"]) # AI 답변 전문 print(data["usage"]) # 토큰 사용량 print(data["grounding_sources"]) # 활용 데이터 소스
curl -X POST https://api.greentu.io/api/chat-sync \
-H "Content-Type: application/json" \
-d '{"message": "자동차보험 손해사정 기준", "session_id": "test_001"}'<!-- GreenTu Law Chat Widget --> <div id="greentu-chat" style="max-width:600px;margin:20px auto;font-family:sans-serif"> <div id="chat-messages" style="height:400px;overflow-y:auto;border:1px solid #e5e7eb; border-radius:12px;padding:16px;background:#f9fafb;margin-bottom:12px"></div> <form id="chat-form" style="display:flex;gap:8px"> <input id="chat-input" type="text" placeholder="보험 분쟁 사안을 질문하세요..." style="flex:1;padding:12px;border:1px solid #d1d5db;border-radius:8px;font-size:14px"> <button type="submit" style="padding:12px 24px;background:#3b82f6;color:#fff; border:none;border-radius:8px;font-weight:600;cursor:pointer">전송</button> </form> </div> <script> (function() { const API = 'https://api.greentu.io/api/chat'; const SID = 'widget_' + Date.now(); const msgs = document.getElementById('chat-messages'); const form = document.getElementById('chat-form'); const input = document.getElementById('chat-input'); form.addEventListener('submit', async (e) => { e.preventDefault(); const q = input.value.trim(); if (!q) return; addMsg('user', q); input.value = ''; const res = await fetch(API, { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({message: q, session_id: SID}) }); const reader = res.body.getReader(); const dec = new TextDecoder(); const el = addMsg('bot', ''); let reply = ''; while(true) { const {done, value} = await reader.read(); if(done) break; for(const line of dec.decode(value).split('\n')) { if(!line.startsWith('data: ')) continue; try { const d = JSON.parse(line.slice(6)); if(d.type==='content') { reply+=d.content; el.textContent=reply; } } catch(e){} } } }); function addMsg(role, text) { const d = document.createElement('div'); d.style.cssText = `margin:8px 0;padding:10px 14px;border-radius:10px;max-width:85%; ${role==='user'?'margin-left:auto;background:#3b82f6;color:#fff' :'background:#e5e7eb;color:#1f2937'};white-space:pre-wrap;font-size:14px`; d.textContent = text; msgs.appendChild(d); msgs.scrollTop = msgs.scrollHeight; return d; } })(); </script>
브라우저에서 직접 API를 호출하여 응답을 확인하세요