API 문서
에브리원툴즈 개발자용 REST API v1. 인증·요청·응답·재시도·크레딧·한도·오류 코드를 한 장에 정리했습니다.
- API 버전1.0.0
기본 정보
API base URL: https://api.everyonetools.com
모든 경로는 API base URL 아래 /v1 로 시작합니다. 요청·응답은 JSON 이고, 모든 응답에 X-Request-Id 헤더가 붙습니다(문의할 때 함께 알려 주세요).
오류는 {"error": {code, message, request_id, details?, retry_after_seconds?}} 봉투로 돌아옵니다. 상태코드·문구 대신 code 로 분기하세요. details 에는 입력값이 담기지 않습니다.
인증
Authorization: Bearer <API 키> 헤더로 인증합니다. 키 원문은 evt_live_ 로 시작하고 대시보드에서 발급하며, 발급·교체 직후 한 번만 보여 줍니다(잃어버리면 교체).
키에는 스코프가 있습니다 — tools:read(도구 목록·설명), tools:run(실행), usage:read(사용량·한도). 발급 때 생략하면 셋 다 받습니다. 부족하면 403 insufficient_scope.
키 관리(발급·교체·폐기)와 구독·예산·환불은 사이트 로그인 토큰으로만 할 수 있고 API 키로는 403 api_key_not_allowed 입니다. 조직당 활성 키는 10개까지입니다.
Authorization: Bearer evt_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
도구
지금 공개된 도구는 3개입니다. GET /v1/tools 가 목록을, GET /v1/tools/{tool_id} 가 설명·input_schema·output_schema·비용(과 파일 도구의 sample_input·file_ttl_hours)을 돌려줍니다. 모르는 입력 필드는 422 로 거절합니다. 문서 도구 doc.quote(견적서 PDF)는 구현과 로컬 검증이 끝났지만 판매 차감량이 아직 정해지지 않아 운영 목록에는 나오지 않습니다 — 아래 설명은 열렸을 때의 계약입니다.
| 도구 | 입력(input) | 출력(output) | 비용 |
|---|---|---|---|
calc.loan대출 이자 계산 |
| principal · annual_interest_rate · loan_term_years · loan_term_months · monthly_payment(월 상환액, 원리금균등) · total_payment · total_interest | 1크레딧 / 성공 호출(basic · call) |
calc.vat부가가치세 계산 |
| input_price · vat_rate · vat_exclusive_price(포함가로 본 공급가액) · vat_inclusive_price(공급가로 본 포함가) · vat_amount | 1크레딧 / 성공 호출(basic · call) |
text.count글자 수 세기 |
| characters_with_spaces · characters_without_spaces · words · lines · sentences · paragraphs | 1크레딧 / 성공 호출(basic · call) |
doc.quote견적서 PDF 만들기 (공개 전 — 차감량 미확정) |
| title · date · quote_no · item_count · pages · totals{supply_amount, vat_amount, total_amount, total_in_words} · file{id, filename, content_type, size_bytes, sha256, download_path, expires_at} | 미확정(flat · 문서 1건) — 로컬 검증은 시험 단가, 판매 단가는 별도 결정 |
실행 요청과 응답
POST /v1/tools/{tool_id}/run 에 본문 {"input": {…}} 을 보냅니다. 동기 도구는 결과를 바로 돌려줍니다(status: completed).
응답의 credits 는 이 호출의 비용(cost), 실행 전 잡아 둔 양(reserved), 확정 차감(charged)입니다. 성공하면 charged = cost, 실패하면 차감하지 않습니다. request_id 는 X-Request-Id 와 같은 값입니다.
POST /v1/tools/calc.loan/run
요청 본문
{
"input": {
"principal": 300000000,
"annual_interest_rate": 4.5,
"loan_term_years": 30
}
}응답(예시 — 값은 설명용)
{
"request_id": "req_01JC3W4YV8F1Z8ZQ3Q0J4H2K9M",
"tool_id": "calc.loan",
"tool_version": "1.0.0",
"status": "completed",
"output": {
"principal": 300000000,
"annual_interest_rate": 4.5,
"loan_term_years": 30,
"loan_term_months": 360,
"monthly_payment": 1520059.47,
"total_payment": 547221409.2,
"total_interest": 247221409.2
},
"credits": { "cost": 1, "reserved": 1, "charged": 1 },
"duration_ms": 3
}{
"error": {
"code": "quota_exceeded",
"message": "오늘의 호출 상한에 닿았습니다.",
"request_id": "req_01JC3W5A0R6C2N0X9Y7B3D1E8F",
"details": { "limit": "daily_calls" },
"retry_after_seconds": 3600
}
}재시도와 Idempotency-Key
네트워크 오류 등으로 재시도할 때는 Idempotency-Key 헤더(영숫자·점·밑줄·하이픈 1~128자, UUID 권장)에 같은 값을 보냅니다. 같은 키의 요청은 한 번만 실행·차감되고, 다시 온 요청은 저장된 응답을 Idempotent-Replayed: true 와 함께 받습니다 — 같은 키 = 한 번 차감.
키는 조직 단위로 24시간 기억합니다. 같은 키를 다른 본문·다른 도구에 쓰면 409 idempotency_conflict, 아직 처리 중이면 409 idempotency_in_progress(Retry-After). 키 없는 재시도는 새 호출로 차감됩니다.
Idempotency-Key: 11111111-2222-4333-8444-555555555555 → 200 OK Idempotent-Replayed: true
도구별 크레딧
도구마다 credit_cost(1단위에 쓰는 크레딧) · cost_class(차감 방식) · cost_unit(과금 단위) · max_units(metered 의 최대 단위 수)가 있고 GET /v1/tools 에 실립니다.
basic: 성공 실행 1회 = 1크레딧. flat: 호출당 고정 단가. metered: 서버가 입력에서 센 단위 수 × credit_cost(크레딧 수와 HTTP 호출 수가 다를 수 있음, max_units 초과는 422). 지금 공개된 3개 도구는 모두 basic 입니다.
실패(검증 오류·도구 오류·시간 초과)는 차감하지 않습니다. 크레딧이 모자라면 실행하지 않고 402 insufficient_credits 입니다. 남은 기간 크레딧은 기간이 끝나면 소멸합니다(이월 없음).
결과 파일(문서 도구)
파일을 만드는 도구(result_kind: file)는 실행 응답의 output.file 에 저장된 결과를 적습니다 — id, filename, content_type, size_bytes, sha256, download_path(/v1/files/{id}), expires_at. 바이트는 응답 본문에 넣지 않습니다.
GET /v1/files/{id} 로 내려받습니다(같은 조직의 키 tools:run 또는 로그인 세션). 다른 조직의 파일은 ID 를 알아도 404 입니다. 다시 내려받아도 생성 크레딧을 다시 차감하지 않고, 잔액이 0 이어도 받을 수 있습니다 — 파일당 횟수 상한과 조직 처리율만 적용합니다. GET /v1/files 는 조직의 최근 결과 파일 목록(state: available · pending · failed · expired · deleted)입니다.
보관 시간(file_ttl_hours — 지금 설정은 로컬 검증용 24시간, 운영 보관 기간은 출시 전 결정)이 지나면 정리 전이라도 410 file_expired 입니다. 멱등 키 보관(24시간)과는 별개의 설정입니다. 같은 Idempotency-Key 로 다시 보내면 저장된 응답을 그대로 받을 뿐 파일을 다시 만들거나 차감하지 않습니다 — 새 파일이 필요하면 새 키로 새 요청을 보내세요. 정산 전(409 file_not_ready)에는 Retry-After 뒤 다시 시도합니다.
생성 실패(렌더링·저장 오류·크기 초과)는 500 으로 끝나고 차감하지 않습니다. 생성 실패와 다운로드 실패는 다릅니다 — 다운로드 오류(404·409·410·429)로 크레딧이 움직이지 않습니다. 입력은 서버 고정 템플릿에만 들어가며(HTML·템플릿 코드·파일 경로·URL 은 받지 않음), 문서 본문은 로그에 남기지 않습니다.
{
"request_id": "req_6f1c9c2d4b7e4a0f9c1d",
"tool_id": "doc.quote",
"status": "completed",
"output": {
"title": "견적서", "date": "2026-11-07", "quote_no": "Q-2026-0001", "item_count": 3, "pages": 1,
"totals": { "vat_mode": "separate", "supply_amount": 2460000, "vat_amount": 246000, "total_amount": 2706000, "total_in_words": "이백칠십만육천" },
"file": {
"id": "01JD2V5Q8M3N7P9R1S4T6W8Y0Z", "filename": "견적서_20261107.pdf", "content_type": "application/pdf",
"size_bytes": 23484, "sha256": "…", "download_path": "/v1/files/01JD2V5Q8M3N7P9R1S4T6W8Y0Z", "expires_at": "2026-11-08T03:00:00Z"
}
},
"credits": { "cost": 5, "reserved": 5, "charged": 5 }
}지급 기간과 잔액
GET /v1/account/limits 가 플랜·레이트 리밋·크레딧 잔액·일일 호출·하루 예산·알림을 돌려줍니다.
credits.period_start / period_end 는 이번 지급 기간(UTC)입니다 — 무료는 매달 1일 00:00 KST 부터 한 달, 구독은 결제된 기간. credits.balance 는 지금 쓸 수 있는 기간 크레딧(아직 실행한 적이 없으면 다음 실행 때 받을 이번 기간 몫), monthly_grant 는 기간의 기본 지급량입니다.
grace_until 은 결제한 기간이 끝나 갱신 결제를 기다리는 유예의 끝(= period_end) — 그때까지 남은 크레딧과 유료 한도가 유지되고 새 지급은 없습니다. topup_balance 는 기간이 넘어가도 남는 추가 충전 크레딧, topup_next_expiry_at 은 그중 가장 먼저 만료되는 묶음의 시각입니다.
한도
레이트 리밋은 조직의 모든 키·서버가 합쳐서 세는 적용 상한이며 보장 성능이 아닙니다(토큰 버킷: T초 동안 최대 burst + 초당 × T 건). 무료 요금제는 하루(KST) 실행 호출 50건, 유료는 일일 상한이 없습니다. 고객이 정한 하루 크레딧 예산(PUT /v1/account/budget, 단위 크레딧)도 같은 방식으로 거절합니다.
| 요금제 | 초당 | 버스트 | 동시 | 하루 실행 |
|---|---|---|---|---|
| Free | 1 | 5 | 2 | 50 |
| Pro | 5 | 10 | 5 | 없음 |
| Business | 20 | 40 | 20 | 없음 |
- 429 rate_limited — 처리율·동시 실행 한도. details.limit 이 requests_per_second 또는 concurrent_requests, Retry-After 헤더 뒤에 재시도.
- 429 quota_exceeded — 일일 호출 상한 또는 하루 예산. details.limit 이 daily_calls 또는 daily_budget, Retry-After 는 다음 날 KST 00:00 까지의 초.
- 402 insufficient_credits — 크레딧 부족(429 가 아님). 실행하지 않았고 차감도 없음.
- 403 organization_suspended — 정지된 조직. 운영자 문의.
- 401 invalid_api_key / invalid_token — 키 또는 로그인 토큰이 틀리거나 폐기·만료.
- 503 service_unavailable / tool_disabled — 저장소 미준비 또는 도구 일시 중지. 잠시 뒤 재시도.
예시
calc.loan 을 실제 입력 필드 이름으로 부르는 예시입니다. 발급한 키는 EVT_API_KEY 환경 변수에 두고(코드·저장소에 직접 적지 않습니다), Idempotency-Key 는 요청마다 새로 만들되 같은 요청의 재시도에는 같은 값을 쓰세요.
curl -X POST "https://api.everyonetools.com/v1/tools/calc.loan/run" \
-H "Authorization: Bearer $EVT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 11111111-2222-4333-8444-555555555555" \
-d '{"input":{"principal":300000000,"annual_interest_rate":4.5,"loan_term_years":30}}'문서 도구 예시 — doc.quote(견적서 PDF, 공개 전)
실행 응답의 output.file.download_path 를 같은 인증으로 한 번 더 호출해 PDF 를 받습니다. 금액·합계는 서버가 계산합니다. 아래 값은 예시입니다(실존 상호·개인정보 아님).
# 1) 만들기 — output.file 에 결과 파일 정보
curl -X POST "https://api.everyonetools.com/v1/tools/doc.quote/run" \
-H "Authorization: Bearer $EVT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 11111111-2222-4333-8444-555555555556" \
-d '{
"input": {
"supplier": {"name": "예시 공급사", "ceo": "홍길동", "business_number": "000-00-00000", "contact": "02-000-0000"},
"recipient": {"name": "예시 고객사", "contact": "담당자 김예시"},
"date": "2026-11-07",
"quote_no": "Q-2026-0001",
"vat_mode": "separate",
"items": [
{"name": "웹사이트 유지보수(월)", "quantity": "3", "unit": "월", "unit_price": 500000},
{"name": "초기 설정", "quantity": "1", "unit": "식", "unit_price": 300000}
]
}
}'
# 2) 내려받기 — download_path 를 같은 키로(재다운로드 무차감)
curl -L -o quote.pdf "https://api.everyonetools.com/v1/files/<output.file.id>" \
-H "Authorization: Bearer $EVT_API_KEY"오류 코드
오류 봉투의 code 전체 목록입니다. HTTP 상태는 참고용이고, 분기는 code 로 하세요.
| HTTP | code | 뜻 |
|---|---|---|
| 401 | missing_credentials | Authorization 헤더가 없습니다. |
| 401 | invalid_api_key | API 키가 틀렸거나 폐기·만료됐습니다. 대시보드에서 키 상태를 확인하거나 교체하세요. |
| 401 | invalid_token | 사이트 로그인 토큰이 유효하지 않습니다(만료 등). 다시 로그인하세요. |
| 401 | reauth_required | 본인 재확인(현재 비밀번호 또는 Google 재확인)이 없거나 틀렸습니다. |
| 402 | insufficient_credits | 크레딧이 모자라 실행하지 않았습니다(차감 없음). 지급 기간이 바뀌면 다시 받습니다. |
| 403 | insufficient_scope | 키의 스코프가 부족합니다(tools:read · tools:run · usage:read). |
| 403 | organization_required | 조직 없는 주체입니다 — 조직이 있어야 크레딧·사용량을 쓸 수 있습니다. |
| 403 | organization_suspended | 조직이 정지되어 도구를 실행할 수 없습니다. 운영자에게 문의하세요. |
| 403 | api_key_not_allowed | 이 작업은 사이트 로그인 토큰으로만 할 수 있습니다(API 키 불가). |
| 403 | forbidden_role | 조직 역할이 부족합니다(owner·admin 만). |
| 404 | tool_not_found | 그 ID 의 도구가 없습니다. GET /v1/tools 로 확인하세요. |
| 404 | key_not_found | 그 조직에 없는 키입니다. |
| 404 | subscription_not_found | 살아 있는 구독이 없습니다. |
| 404 | payment_not_found | 모르는 결제 ID 입니다. |
| 409 | idempotency_conflict | 같은 Idempotency-Key 가 다른 본문·다른 도구에 쓰였습니다. 새 요청에는 새 키를 쓰세요. |
| 409 | idempotency_in_progress | 같은 키의 요청이 아직 처리 중입니다. Retry-After 뒤에 다시 보내세요. |
| 409 | key_not_active | 이미 교체 중이거나 폐기·만료된 키입니다. |
| 409 | subscription_state | 지금 구독 상태에서는 할 수 없는 요청입니다. |
| 409 | refund_state | 지금 환불 상태에서는 할 수 없는 요청입니다. |
| 422 | validation_error | 요청·입력 검증 실패 — details 에 위치·유형·메시지가 있습니다(입력값은 담지 않습니다). |
| 422 | key_limit_reached | 조직당 활성 키 상한(10개)에 닿았습니다. 안 쓰는 키를 폐기하세요. |
| 429 | rate_limited | 조직의 처리율·동시 실행 한도를 넘었습니다(details.limit = requests_per_second · concurrent_requests). Retry-After 뒤에 다시 보내세요. |
| 429 | quota_exceeded | 일일 호출 상한(details.limit = daily_calls) 또는 고객이 정한 하루 예산(daily_budget)을 넘었습니다. Retry-After 는 다음 날 KST 00:00 까지의 초입니다. |
| 500 | internal_error | 서버 오류입니다. request_id 와 함께 문의하세요. |
| 500 | tool_execution_failed | 도구 실행이 실패했습니다(차감 없음). |
| 503 | service_unavailable | 저장소가 준비되지 않았습니다. 잠시 뒤 다시 시도하세요. |
| 503 | tool_disabled | 도구가 일시 중지됐습니다. |
| 504 | tool_timeout | 실행 시간을 넘겼습니다(차감 없음). |