시작하기
API 와 웹훅은 연동형 요금제에서 씁니다.
콘솔의 연동·API 메뉴에서 키를 발급하고, 호출마다 머리글에 붙이세요.
Authorization: Bearer ls_live_••••••••••••••••
Content-Type: application/json
| 주소 | https://leadsign.co.kr/api/v1 |
|---|---|
| 형식 | 요청과 응답 모두 JSON (UTF-8). 시각은 ISO-8601, 시간대가 없으면 한국 시간으로 봅니다. |
| 요청의 주인 | API 로 만든 요청은 키를 발급한 사람의 이름으로 콘솔 문서함에 쌓입니다. |
| 한도 | 요금제의 서명 요청 건수가 그대로 적용됩니다. 넘으면 402 plan_limit 이 옵니다. |
키는 발급할 때 한 번만 보입니다. 브라우저나 앱 코드에 넣지 말고 서버에만 두세요.
템플릿 목록
콘솔에서 문서와 입력란을 놓아 둔 템플릿만 나옵니다.
GET/templates
{
"data": [
{
"id": 12,
"name": "근로계약서",
"description": null,
"signerCount": 2,
"prefillLabels": ["연봉", "입사일"]
}
]
}
signerCount 만큼 서명자를 보내야 합니다.
prefillLabels 는 요청을 보낼 때 미리 채울 수 있는 입력란의 이름입니다.
서명 요청 보내기
POST/requests
curl https://leadsign.co.kr/api/v1/requests \
-H "Authorization: Bearer $LEADSIGN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": 12,
"title": "2026년 근로계약서 — 홍길동",
"signers": [
{ "name": "김대표", "email": "ceo@example.com" },
{ "name": "홍길동", "phone": "010-1234-5678", "notifyMethod": "KAKAO" }
],
"prefill": { "연봉": "42,000,000원", "입사일": "2026-12-01" },
"externalRef": "HR-2026-0412",
"cc": ["hr@example.com"],
"expiresAt": "2026-12-15T18:00:00+09:00"
}'
| 이름 | 설명 |
|---|---|
templateId 필수 | 보낼 템플릿 |
signers 필수 | 템플릿의 참여자 차례대로. name 과 함께 email 또는 phone.notifyMethod 는 EMAIL·KAKAO, 비우면 이메일이 있을 때 이메일로 보냅니다. company 를 넣으면 회사 이름 칸에 들어갑니다. |
title | 문서 이름. 비우면 템플릿 이름 |
sequential | 차례대로 서명할지. 기본 true |
prefill | 입력란 이름 → 값. 글자·날짜·체크 칸만 채울 수 있고, 서명자가 고칠 수 있습니다. |
externalRef | 사내 시스템의 번호. 조회와 웹훅에 그대로 실려 옵니다. (100자) |
cc | 서명이 끝나면 완성본을 함께 받을 이메일. 5명까지 |
expiresAt | 서명 기한. 이때까지 끝나지 않으면 expired 로 닫힙니다. |
scheduledAt | 예약 발송 시각. 비우면 곧바로 보냅니다. |
성공하면 201 과 함께 요청을 돌려줍니다. 모양은 요청 조회와 같습니다.
요청 조회
GET/requests/{id}
GET/requests?page=0&size=20
{
"data": {
"id": 4821,
"title": "2026년 근로계약서 — 홍길동",
"status": "in_progress",
"statusLabel": "상대 서명 필요",
"externalRef": "HR-2026-0412",
"origin": "API",
"templateId": 12,
"documentNo": null,
"sequential": true,
"createdAt": "2026-11-02T10:12:03+09:00",
"sentAt": "2026-11-02T10:12:04+09:00",
"scheduledAt": null,
"expiresAt": "2026-12-15T18:00:00+09:00",
"completedAt": null,
"signers": [
{ "id": 9910, "order": 1, "name": "김대표", "email": "ceo@example.com", "phone": null,
"notifyMethod": "EMAIL", "status": "signed", "signedAt": "2026-11-02T10:20:41+09:00", "rejectReason": null },
{ "id": 9911, "order": 2, "name": "홍길동", "email": null, "phone": "010-1234-5678",
"notifyMethod": "KAKAO", "status": "pending", "signedAt": null, "rejectReason": null }
]
}
}
| status | 뜻 |
|---|---|
scheduled | 예약해 두어 아직 나가지 않았습니다 |
in_progress | 서명을 받는 중입니다 |
completed | 모두 서명했고 완성본이 있습니다 |
canceled | 요청자가 취소했거나 서명자가 거절했습니다 |
expired | 서명 기한이 지났습니다 |
서명 주소 받기
안내를 리드싸인 대신 사내 채널로 보내거나, 사내 화면에 서명 창을 띄울 때 씁니다.
GET/requests/{id}/signers/{signerId}/link
{ "data": { "signerId": 9911, "url": "https://leadsign.co.kr/sign/3f9c…" } }
이 주소를 가진 사람은 그 서명자로 서명 화면에 들어옵니다.
본인에게만 전하고 로그나 공개된 곳에 남기지 마세요.
완성본 받기
서명이 끝난 뒤에만 받을 수 있습니다. 아직이면 409 가 옵니다.
GET/requests/{id}/document서명 완료 PDF
GET/requests/{id}/audit-trail감사추적인증서 PDF
취소·재알림
POST/requests/{id}/cancel
POST/requests/{id}/remind지금 차례인 서명자에게 안내를 다시 보냅니다
오류
{ "error": { "code": "invalid_request", "message": "이 템플릿은 서명자 2명이 필요합니다. 1명이 왔습니다." } }
| HTTP | code | 언제 |
|---|---|---|
| 400 | invalid_request invalid_json | 보낸 값이 틀렸습니다. message 에 무엇이 틀렸는지 적혀 있습니다. |
| 401 | unauthorized | 키가 없거나, 폐기되었거나, 요금제에서 API 를 쓸 수 없습니다. |
| 402 | plan_limit | 요금제 한도(건수·서명자 수 등)를 넘었습니다. |
| 404 | not_found | 없는 요청이거나 다른 회사의 요청입니다. |
| 409 | invalid_state | 지금 상태에서는 할 수 없는 일입니다. |
웹훅
콘솔의 연동·API 에서 받을 주소를 등록하면, 일이 생길 때마다 JSON 을 POST 합니다.
2xx 로 답하지 않으면 1분, 5분, 30분, 2시간, 6시간 뒤에 다시 보냅니다.
| type | 언제 |
|---|---|
request.sent | 요청이 나갔습니다 (예약은 실제로 나갈 때) |
signer.signed | 서명자 한 사람이 서명했습니다. data.signer 가 함께 옵니다 |
request.completed | 모두 서명해 완성본이 만들어졌습니다 |
request.rejected | 서명자가 거절했습니다 |
request.canceled | 요청자가 취소했습니다 |
request.expired | 서명 기한이 지났습니다 |
POST /your/webhook
LeadSign-Event: request.completed
LeadSign-Delivery: evt_8c1d…
LeadSign-Signature: t=1793584800,v1=5b2f…
{
"id": "evt_8c1d…",
"type": "request.completed",
"createdAt": "2026-11-02T15:40:00+09:00",
"data": { "request": { "id": 4821, "status": "completed", "externalRef": "HR-2026-0412", … } }
}
같은 일이 두 번 올 수 있습니다. id 로 이미 처리한 것인지 가려 주세요.
웹훅 서명 확인
등록할 때 받은 비밀값(whsec_…)으로 t + "." + 본문 의 HMAC-SHA256 을 구해 v1 과 견주세요.
t 가 5분보다 오래되었으면 버리는 것이 안전합니다.
// Node.js
const crypto = require('crypto');
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto.createHmac('sha256', secret)
.update(parts.t + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
본문은 받은 그대로의 바이트로 계산해야 합니다. JSON 으로 읽었다가 다시 쓰면 값이 달라집니다.