계약서 한 장, 링크 하나로 끝내는 전자계약

API 가이드

사내 시스템에서
바로 서명을 요청하세요

템플릿 하나와 서명자 정보만 보내면 요청이 나갑니다.
서명이 끝나면 웹훅으로 곧바로 알려 드립니다.

시작하기

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서명 기한이 지났습니다

완성본 받기

서명이 끝난 뒤에만 받을 수 있습니다. 아직이면 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명이 왔습니다." } }
HTTPcode언제
400invalid_request invalid_json보낸 값이 틀렸습니다. message 에 무엇이 틀렸는지 적혀 있습니다.
401unauthorized키가 없거나, 폐기되었거나, 요금제에서 API 를 쓸 수 없습니다.
402plan_limit요금제 한도(건수·서명자 수 등)를 넘었습니다.
404not_found없는 요청이거나 다른 회사의 요청입니다.
409invalid_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 으로 읽었다가 다시 쓰면 값이 달라집니다.

사내 시스템과 연동하시나요?
먼저 이야기부터 들어 보세요

쓰시는 계약서와 보안 요건에 맞춰 어떻게 놓으면 좋을지 함께 봐 드립니다.