PaySign External API
v1.0 — pdf.paysign.co.kr
PaySign External API를 사용하면 외부 애플리케이션에서 PDF 업로드, 필드 오버레이 머지, 전자서명 요청을 프로그래밍 방식으로 수행할 수 있습니다.
문서 업로드
PDF, DOCX 업로드 및 자동 변환 (최대 50MB)
Base URL
https://pdf.paysign.co.kr/api/v1
인증
모든 API 요청에는 Authorization 헤더에 Bearer 토큰으로 API 키를 포함해야 합니다.
API 키는 대시보드의 API 관리 탭에서 생성할 수 있습니다.
// 요청 헤더
Authorization: Bearer ps_live_a1b2c3d4e5f6...
보안 주의사항
- API 키는 생성 시 한 번만 표시됩니다. 안전한 곳에 보관하세요.
- 키를 클라이언트 사이드 코드에 노출하지 마세요.
- 키가 유출된 경우 즉시 비활성화하고 새 키를 생성하세요.
에러 처리
모든 에러 응답은 동일한 JSON 구조를 따릅니다.
{
"error": "error_code",
"message": "사람이 읽을 수 있는 에러 메시지"
}
| 상태 코드 | 설명 |
| 400 | 잘못된 요청 (필수 파라미터 누락, 유효하지 않은 값) |
| 401 | 인증 실패 (API 키 누락 또는 유효하지 않음) |
| 404 | 리소스를 찾을 수 없음 |
| 429 | Rate Limit 초과 또는 월별 쿼터 초과 |
| 500 | 서버 내부 오류 |
Rate Limit
모든 API 키에는 분당 요청 수(RPM)와 월별 쿼터가 적용됩니다. 기본값은 60 RPM / 월 1,000회입니다.
응답 헤더에 현재 제한 상태가 포함됩니다:
// 응답 헤더
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
Retry-After: 32 // 429 응답 시에만
쿼터 초과 시
429 응답과 함께 현재 사용량, 쿼터, 리셋 시점이 반환됩니다. 월별 쿼터는 매월 1일 자동 리셋됩니다.
POST
/api/v1/pdf/upload
PDF, DOCX(Word), HWP(한글) 파일을 업로드합니다. DOCX/HWP 파일은 서버에서 자동으로 PDF로 변환됩니다. multipart/form-data 형식으로 전송합니다.
지원 포맷
PDF (.pdf), Microsoft Word (.docx), 한글 (.hwp, .hwpx) — DOCX는 Google Drive API, HWP/HWPX는 LibreOffice + H2Orestart 기반 자동 PDF 변환.
요청 파라미터
| 필드 | 타입 | 설명 |
| file필수 | File | PDF, DOCX, HWP 파일 (최대 50MB) |
응답 예시
{
"document_id": "550e8400-e29b-41d4-a716-446655440000",
"pdf_path": "/uploads/a1b2c3d4e5f6/2026/03/550e8400-....pdf",
"page_count": 3,
"file_size": 245760,
"filename": "contract.pdf",
"original_format": "docx"
}
original_format — 원본 파일 형식. "pdf" 또는 "docx". DOCX 업로드 시에도 pdf_path는 변환된 PDF 경로를 반환합니다.
cURL 예시
# PDF 업로드
curl -X POST https://pdf.paysign.co.kr/api/v1/pdf/upload \
-H "Authorization: Bearer ps_live_YOUR_KEY" \
-F "file=@contract.pdf"
# DOCX 업로드 (자동 PDF 변환)
curl -X POST https://pdf.paysign.co.kr/api/v1/pdf/upload \
-H "Authorization: Bearer ps_live_YOUR_KEY" \
-F "file=@contract.docx"
POST
/api/v1/pdf/merge
업로드된 PDF에 텍스트, 서명, 체크박스 필드를 오버레이합니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| pdf_path필수 | string | 업로드 응답의 pdf_path 값 |
| fields필수 | array | 오버레이할 필드 배열 |
| title | string | PDF 메타데이터 제목 |
fields 배열 항목
| 필드 | 타입 | 설명 |
| field_type | string | text | signature | checkbox (기본: text) |
| page필수 | number | 페이지 번호 (1부터 시작) |
| x필수 | number | 왼쪽 상단 X 좌표 (pt) |
| y필수 | number | 왼쪽 상단 Y 좌표 (pt) |
| w필수 | number | 너비 (pt) |
| h필수 | number | 높이 (pt) |
| value | string | 텍스트 값 (text/checkbox) |
| sig_data | string | 서명 이미지 Base64 (signature) |
요청 예시
curl -X POST https://pdf.paysign.co.kr/api/v1/pdf/merge \
-H "Authorization: Bearer ps_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"pdf_path": "/uploads/a1b2.../doc.pdf",
"fields": [
{ "field_type": "text", "page": 1, "x": 100, "y": 200, "w": 200, "h": 20, "value": "홍길동" },
{ "field_type": "text", "page": 1, "x": 100, "y": 240, "w": 200, "h": 20, "value": "2026-03-28" }
],
"title": "근로계약서"
}'
응답 예시
{
"merged_pdf_path": "/uploads/a1b2.../api_550e8400-....pdf",
"file_size": 312400
}
GET
/api/v1/pdf/:id/download?path={pdf_path}
업로드 또는 머지된 PDF 파일을 다운로드합니다.
요청 파라미터
| 필드 | 위치 | 설명 |
| path필수 | query | pdf_path 또는 merged_pdf_path 값 |
cURL 예시
curl -H "Authorization: Bearer ps_live_YOUR_KEY" \
"https://pdf.paysign.co.kr/api/v1/pdf/download?path=/uploads/a1b2.../api_doc.pdf" \
-o merged.pdf
응답: application/pdf 바이너리 스트림
POST
/api/v1/templates
PDF 문서를 기반으로 재사용 가능한 템플릿을 생성합니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| name필수 | string | 템플릿 이름 |
| pdf_path필수 | string | 업로드된 PDF 경로 |
| fields | array | 사전 정의 필드 (선택사항) |
응답 예시
{
"template_id": 1,
"name": "근로계약서 양식",
"pdf_path": "/uploads/a1b2.../doc.pdf",
"field_count": 0
}
GET
/api/v1/templates
현재 API 키에 등록된 템플릿 목록을 조회합니다.
{
"templates": [
{
"id": 1,
"name": "근로계약서 양식",
"pdf_path": "/uploads/a1b2.../doc.pdf",
"field_count": 5,
"created_at": "2026-03-28T10:00:00.000Z",
"updated_at": "2026-03-28T10:30:00.000Z"
}
]
}
GET
/api/v1/templates/:id
특정 템플릿의 상세 정보와 필드 설정을 조회합니다.
{
"template_id": 1,
"name": "근로계약서 양식",
"pdf_path": "/uploads/a1b2.../doc.pdf",
"fields": [
{ "field_type": "name", "page": 1, "x": 100, "y": 200, "w": 140, "h": 36 },
{ "field_type": "signature", "page": 1, "x": 100, "y": 600, "w": 160, "h": 50 }
],
"field_count": 2,
"created_at": "2026-03-28T10:00:00.000Z"
}
PUT
/api/v1/templates/:id
템플릿의 이름이나 필드 설정을 수정합니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| name | string | 새 템플릿 이름 |
| fields | array | 새 필드 설정 배열 |
// 응답
{ "updated": true }
DELETE
/api/v1/templates/:id
템플릿을 비활성화합니다 (소프트 삭제).
{ "deleted": true }
POST
/api/v1/templates/:id/sign
템플릿에 설정된 필드를 기반으로 서명 요청을 자동 생성합니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| signer_name | string | 서명자 이름 |
| signer_email | string | 서명자 이메일 |
| callback_url | string | 서명 완료 시 웹훅 URL |
| expires_hours | number | 만료 시간 (기본 72h, 최대 720h) |
응답 예시
{
"request_id": "550e8400-...",
"sign_url": "https://pdf.paysign.co.kr/sign/abc123...",
"template_id": 1,
"field_count": 5,
"expires_at": "2026-03-31T12:00:00.000Z",
"status": "pending"
}
POST
/api/v1/editor/session
필드 에디터 세션을 생성합니다. 반환된 editor_url을 iframe에 삽입하면 사용자가 드래그&드롭으로 PDF 위에 입력 필드를 배치할 수 있습니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| pdf_path | string | 에디터에 표시할 PDF 경로 (pdf_path 또는 template_id 중 하나 필수) |
| template_id | number | 기존 템플릿 ID (필드를 불러와서 편집) |
응답 예시
{
"session_token": "a1b2c3d4e5f6...",
"editor_url": "https://pdf.paysign.co.kr/editor/a1b2c3d4e5f6...",
"pdf_path": "/uploads/a1b2.../doc.pdf",
"expires_at": "2026-03-28T14:00:00.000Z"
}
사용 흐름
- PDF 업로드 후 pdf_path 획득
- 템플릿 생성 (POST /templates)
- 에디터 세션 생성 (POST /editor/session)
- editor_url을 iframe에 삽입
- 사용자가 필드를 드래그&드롭으로 배치 후 저장
- postMessage로 fields_config 수신
- 템플릿 기반 서명 요청 (POST /templates/:id/sign)
iframe 삽입 예시
// 에디터 세션 생성 후
const iframe = document.createElement('iframe');
iframe.src = response.editor_url;
iframe.style.cssText = 'width:100%;height:700px;border:none;';
document.getElementById('editor-container').appendChild(iframe);
// 저장 이벤트 수신
window.addEventListener('message', (e) => {
if (e.data?.type === 'paysign:fields_saved') {
console.log('저장된 필드:', e.data.fields);
}
});
JS SDK
더 편리한 통합을 위해 JS SDK를 제공합니다. iframe 생성, postMessage 핸들링, 라이프사이클 관리를 자동화합니다.
설치
<script src="https://pdf.paysign.co.kr/sdk/paysign-editor.js"></script>
사용법
const editor = new PaySignEditor({
container: '#editor-container',
sessionToken: 'abc123...',
editorUrl: 'https://...',
onSave: (fields) => { console.log('필드 저장:', fields); },
onCancel: () => { console.log('에디터 취소'); },
onReady: () => { console.log('에디터 로드 완료'); },
});
// 현재 필드 가져오기
const fields = await editor.getFields();
// 정리
editor.destroy();
postMessage 이벤트
| 이벤트 | 설명 |
paysign:fields_saved | 사용자가 필드를 저장 — fields 배열 포함 |
paysign:editor_cancelled | 사용자가 취소 클릭 |
paysign:fields_data | getFields() 응답 |
필드 타입
| 타입 | 기본 크기 | 설명 |
name | 140 x 36 | 이름 |
text | 160 x 36 | 텍스트 |
email | 180 x 36 | 이메일 |
phone | 160 x 36 | 전화번호 |
address | 220 x 36 | 주소 |
birthdate | 160 x 36 | 생년월일 |
date | 140 x 36 | 날짜 |
checkbox | 28 x 28 | 체크박스 |
signature | 160 x 50 | 서명 |
POST
/api/v1/sign/request
서명 요청을 생성합니다. 서명자에게 전달할 수 있는 고유 서명 링크가 반환됩니다.
요청 본문 (JSON)
| 필드 | 타입 | 설명 |
| pdf_path필수 | string | 서명할 PDF 경로 |
| fields필수 | array | 서명/입력 필드 설정 (머지와 동일 구조) |
| signer_name | string | 서명자 이름 |
| signer_email | string | 서명자 이메일 |
| callback_url | string | 서명 완료 시 웹훅 URL |
| expires_in_hours | number | 만료 시간 (기본: 72시간) |
응답 예시
{
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"sign_url": "https://pdf.paysign.co.kr/ext-sign/abc123...",
"status": "pending",
"expires_at": "2026-03-31T12:00:00.000Z",
"signer_name": "홍길동",
"signer_email": "hong@example.com"
}
GET
/api/v1/sign/:requestId
서명 요청의 현재 상태를 조회합니다.
응답 예시
{
"request_id": "550e8400-...",
"status": "signed", // pending | signed | expired | cancelled
"signer_name": "홍길동",
"signed_at": "2026-03-28T15:30:00.000Z",
"merged_pdf_path": "/uploads/.../signed_doc.pdf",
"expires_at": "2026-03-31T12:00:00.000Z"
}
상태 흐름
pending → signed (서명 완료) / expired (기한 만료) / cancelled (취소)
POST
/api/v1/sign/:requestId/cancel
대기 중인 서명 요청을 취소합니다. 이미 서명되었거나 만료된 요청은 취소할 수 없습니다.
{
"request_id": "550e8400-...",
"status": "cancelled"
}
GET
/api/v1/usage
현재 API 키의 사용량과 쿼터 정보를 조회합니다.
{
"api_key": "Production API",
"quota": 1000,
"current_usage": 127,
"monthly": {
"request_count": 127,
"pdf_upload_count": 45,
"pdf_merge_count": 38,
"sign_request_count": 12
},
"daily": [
{ "date": "2026-03-27", "count": 23, "avg_response_time": 145 },
...
]
}
빠른 시작 가이드
3단계로 첫 번째 PDF를 생성하세요.
1
PDF 업로드
curl -X POST https://pdf.paysign.co.kr/api/v1/pdf/upload \
-H "Authorization: Bearer $API_KEY" \
-F "file=@template.pdf"
2
필드 머지
curl -X POST https://pdf.paysign.co.kr/api/v1/pdf/merge \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"pdf_path": "/uploads/.../template.pdf",
"fields": [
{ "page": 1, "x": 72, "y": 700, "w": 200, "h": 18, "value": "PaySign Corp." },
{ "page": 1, "x": 72, "y": 680, "w": 200, "h": 18, "value": "2026-03-28" }
]
}'
3
결과 다운로드
curl -H "Authorization: Bearer $API_KEY" \
"https://pdf.paysign.co.kr/api/v1/pdf/download?path=/uploads/.../api_merged.pdf" \
-o result.pdf
웹훅
서명 완료 등 이벤트 발생 시 등록된 URL로 HTTP POST 요청을 전송합니다.
웹훅 URL은 대시보드에서 설정할 수 있습니다.
이벤트 타입
| 이벤트 | 설명 |
| sign.completed | 서명이 완료됨 |
| sign.expired | 서명 요청이 만료됨 |
웹훅 페이로드 예시
{
"event": "sign.completed",
"timestamp": "2026-03-28T15:30:00.000Z",
"data": {
"request_id": "550e8400-...",
"status": "signed",
"signer_name": "홍길동",
"signed_at": "2026-03-28T15:30:00.000Z",
"merged_pdf_path": "/uploads/.../signed.pdf"
}
}
서명 검증 (HMAC-SHA256)
웹훅 시크릿이 설정된 경우 X-PaySign-Signature 헤더에 HMAC 서명이 포함됩니다.
// Node.js 검증 예시
const crypto = require('crypto');
function verifyWebhook(rawBody, signature, secret) {
const expected = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(rawBody).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature), Buffer.from(expected)
);
}