지금 가입하면 문서 3건 무료 · 카드 등록 없이 바로 시작해요무료로 시작하기 ›

개발자

REST API · 웹훅

ERP·인사·CRM 같은 사내 시스템에서 계약서를 만들어 보내고, 서명·체결 소식을 바로 받아요. API 키는 회사 관리 › API·웹훅에서 소유자·관리자가 만들어요.

인증

모든 요청의 Authorization 헤더에 API 키를 넣어요. 키는 만들 때 한 번만 보여요. 1분에 120번까지 부를 수 있어요.

Authorization: Bearer sp_live_xxxxxxxxxxxxxxxxxxxxxxxx

주소

POST/v1/envelopes파일(multipart file) + data(JSON)로 문서를 만들고, send:true 면 바로 보내요.
GET/v1/envelopes보낸 문서 목록(status·q·limit).
GET/v1/envelopes/{id}상태·서명인·자리·체결본 지문.
POST/v1/envelopes/{id}/send초안을 보내요.
POST/v1/envelopes/{id}/void서명 요청을 취소해요(reason).
GET/v1/envelopes/{id}/events감사 기록(열람·동의·서명·발송).
GET/v1/envelopes/{id}/final.pdf체결본 PDF(인증서·전자 봉인 포함).

예: 계약서 보내기

받는 사람만 주면 AI가 서명 자리를 찾아 배정해요. 자리를 직접 정하려면 fields에 쪽 비율 좌표(0~1)를 넣어요.

curl https://signpen.ai/v1/envelopes \
  -H "Authorization: Bearer $SIGNPEN_KEY" \
  -F file=@contract.pdf \
  -F 'data={
    "title": "용역 계약서",
    "message": "검토 후 서명 부탁드립니다.",
    "expire_days": 14,
    "remind_days": 3,
    "recipients": [
      { "name": "김민지", "email": "minji@example.com", "party": "갑" },
      { "name": "Alex Kim", "email": "alex@example.com", "party": "을", "lang": "en", "auth_method": "email_otp" }
    ],
    "send": true
  }'

응답의 data.status가 sent 면 메일이 나간 거예요. 요금은 보낼 때 회사 크레딧에서 차감돼요.

받는 사람 항목

name, email필수
rolesigner(기본) 또는 cc(참조 — 사본만)
party문서 속 호칭(갑·을·근로자…). AI가 찾은 자리를 이 사람에게 배정해요.
orderrouting이 sequential 일 때 순서
langko 또는 en — 메일·서명 화면 언어
auth_methodnone · code(access_code 필요) · email_otp

웹훅

회사 관리 › API·웹훅에서 https 주소를 등록하면 아래 사건마다 JSON을 POST 해요. 2xx가 아니면 1분·5분·30분·2시간·6시간 뒤에 다시 보내요.

envelope.sent보냄
recipient.viewed받는 사람이 열어 봄
recipient.signed한 사람이 서명
envelope.declined거절 — 요청 멈춤
recipient.delegated서명 위임
envelope.completed모두 서명 — 체결본 준비됨
envelope.voided보낸 사람이 취소
envelope.expired기한 지남

진짜 싸인펜이 보낸 것인지 요청 헤더의 SignPen-Signature로 확인하세요. t는 보낸 시각(초), v1은 「t.본문」을 웹훅 비밀로 HMAC-SHA256 한 값이에요. 5분보다 오래된 요청은 버리세요.

// Node.js
import crypto from 'node:crypto';
const [t, v1] = req.get('SignPen-Signature').split(',').map((p) => p.split('=')[1]);
const want = crypto.createHmac('sha256', process.env.SIGNPEN_WEBHOOK_SECRET).update(`${t}.${rawBody}`).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(want)) && Date.now() / 1000 - Number(t) < 300;
{
  "id": "evt_…",
  "type": "envelope.completed",
  "created_at": "2026-10-18T09:12:03.120Z",
  "data": { "envelope_id": "…", "title": "용역 계약서", "status": "completed", "sent_at": "…", "completed_at": "…", "final_sha256": "…" }
}

오류

오류는 HTTP 상태와 함께 { "error": { "code", "message" } }로 와요. 401 키 오류 · 404 없는 문서 · 422 보낼 준비 안 됨(problems에 이유) · 429 너무 잦은 요청.