고객사의 서비스 화면 안에서 서명 화면을 직접 구현하는 방법을 안내합니다.
서명자가 이메일/카카오톡 알림 없이 서비스 내에서 바로 서명할 수 있습니다.
일반 연동 vs 임베디드 연동
| 일반 연동 | 임베디드 연동 | |
|---|---|---|
| 서명자 알림 | 이메일 / 카카오톡 자동 발송 | 발송 안 함 |
| 서명 URL | 직접 받을 수 없음 | sign_url / token으로 응답 |
| 서명 화면 | 서명자가 알림 클릭 후 이동 | 서비스 내 새 탭 / 새 창으로 직접 표시 |
| 활용 예시 | 계약서 발송, 비대면 서명 요청 | 회원가입 동의, 서비스 내 즉시 서명 |
임베디드 연동은 언제 사용하나요?서명자가 지금 바로 서비스 화면에 있는 상황에서 서명을 받아야 할 때 사용합니다.
예를 들어 회원가입 마지막 단계에서 개인정보 동의서를 받거나, 앱 화면에서 계약서에 바로 서명하게 할 때 적합합니다.
iframe은 지원하지 않습니다보안 취약점, 브라우저 호환성 이슈, 페이지 로딩 성능 문제로 인해 iframe 방식은 지원하지 않습니다.
새 탭 또는 새 창 방식으로 서명 화면을 열어 주시기 바랍니다.
이런 순서로 진행합니다
1. 문서 시작하기
일반 문서 시작 API와 동일하지만, export_api_info 파라미터에 is_embed: true를 추가합니다.
이 설정을 하면 이메일 / 카카오톡 알림이 발송되지 않고, 응답에 token과 sign_url이 포함됩니다.
POST /api/v3/workflows/start
export_api_info 상세 파라미터
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
url | string | Y | 서명 완료 시 데이터를 수신할 서버 URL |
api_type | string | Y | 수신 시점: StartAndEnd (시작+완료) / ALL (모든 단계) |
is_embed | boolean | Y | true 설정 시 임베디드 연동 활성화 |
link_type | string | N | 완료 문서 URL 타입: viewer (미리보기) / download (다운로드) |
authorization | string | N | Export API 요청 헤더의 Authorization 값 |
요청 예시
curl -X POST "https://docs.esignon.net/api/v3/workflows/start" \
-H "Authorization: esignon {access_token}" \
-H "Content-Type: application/json" \
-d '{
"workflow_name": "2026_개인정보동의서_홍길동",
"template_id": 753,
"recipient_list": [
{
"order": 1,
"name": "홍길동",
"email": "010-1234-5678"
}
],
"export_api_info": {
"url": "https://your-server.com/esignon/webhook",
"api_type": "StartAndEnd",
"is_embed": true,
"link_type": "viewer"
}
}'const response = await fetch("https://docs.esignon.net/api/v3/workflows/start", {
method: "POST",
headers: {
"Authorization": "esignon {access_token}",
"Content-Type": "application/json"
},
body: JSON.stringify({
workflow_name: "2026_개인정보동의서_홍길동",
template_id: 753,
recipient_list: [
{ order: 1, name: "홍길동", email: "010-1234-5678" }
],
export_api_info: {
url: "https://your-server.com/esignon/webhook",
api_type: "StartAndEnd",
is_embed: true,
link_type: "viewer"
}
})
});
const data = await response.json();
const token = data.token; // 서명 URL 직접 구성 시 사용
const signUrl = data.sign_url; // 바로 사용 가능한 서명 URLimport requests
response = requests.post(
"https://docs.esignon.net/api/v3/workflows/start",
headers={
"Authorization": "esignon {access_token}",
"Content-Type": "application/json"
},
json={
"workflow_name": "2026_개인정보동의서_홍길동",
"template_id": 753,
"recipient_list": [
{ "order": 1, "name": "홍길동", "email": "010-1234-5678" }
],
"export_api_info": {
"url": "https://your-server.com/esignon/webhook",
"api_type": "StartAndEnd",
"is_embed": True,
"link_type": "viewer"
}
}
)
data = response.json()
token = data["token"] # 서명 URL 직접 구성 시 사용
sign_url = data["sign_url"] # 바로 사용 가능한 서명 URL응답 예시
{
"workflow_id": 98765,
"workflow_name": "2026_개인정보동의서_홍길동",
"language": "ko-KR",
"token": "FAEx6i%2BuVzYe...",
"sign_url": "https://docs.esignon.net/mail/sign?token=...",
"next_name": "홍길동",
"next_email": "010-1234-5678"
}| 응답 필드 | 설명 |
|---|---|
token | 서명 URL 직접 구성 시 사용하는 토큰 |
sign_url | 바로 사용 가능한 서명 화면 URL |
next_name | 다음 서명 차례인 서명자 이름 |
next_email | 다음 서명 차례인 서명자 이메일 |
2. 서명 URL 구성하기
응답으로 받은 token을 사용해 서명 URL을 직접 구성할 수 있습니다.
URL에 파라미터를 추가하여 서명 완료 후 동작을 제어합니다.
GET https://docs.esignon.net/api/{companyId}/sign?token={token}
선택 파라미터
| 파라미터 | 값 | 설명 |
|---|---|---|
callback_fn | true | 서명 완료 후 팝업의 닫기 버튼 클릭 시 부모 페이지로 콜백 이벤트를 전달합니다 |
next_sign | false | 서명 완료 팝업에서 "다음 문서 작성하기" 버튼을 숨깁니다 |
lang | ko / en / ja | 서명 화면 언어를 설정합니다 (기본값: ko) |
📷 next_sign=false 적용 시 화면 비교
| 기존 완료 팝업 | next_sign=false 적용 팝업 |
|---|---|
![]() | ![]() |
URL 구성 예시
콜백 이벤트만 사용
https://docs.esignon.net/api/{companyId}/sign?token={token}&callback_fn=true
다음 문서 작성 버튼만 숨기기
https://docs.esignon.net/api/{companyId}/sign?token={token}&next_sign=false
콜백 + 다음 문서 작성 버튼 숨기기 (권장)
https://docs.esignon.net/api/{companyId}/sign?token={token}&callback_fn=true&next_sign=false
새 탭 / 새 창으로 열기
// 서명 URL 구성
const signPageUrl = `https://docs.esignon.net/api/${companyId}/sign?token=${token}&callback_fn=true&next_sign=false&lang=ko`;
// 새 탭으로 열기
window.open(signPageUrl, '_blank');
// 새 창으로 열기 (크기 지정)
window.open(signPageUrl, '_blank', 'width=1200, height=800, top=100, left=100');
팝업 차단 주의브라우저의 팝업 차단 기능이 활성화된 경우 서명 창이 열리지 않을 수 있습니다.
팝업 차단이 감지되면 사용자에게 팝업 허용을 안내하는 메시지를 표시하시기 바랍니다.try { window.open(signPageUrl, '_blank'); } catch (e) { alert("팝업 차단이 설정되어 있습니다. 팝업을 허용한 후 다시 시도해 주세요."); }
3. 서명 완료 처리하기
콜백 이벤트 수신
callback_fn=true로 설정한 경우, 서명 완료 후 팝업에서 닫기 버튼을 클릭하면 부모 페이지로 이벤트가 전달됩니다.
부모 페이지에서 아래와 같이 이벤트를 수신합니다.
window.addEventListener("message", function (e) {
console.log(e.data); // 서명 완료 이벤트 데이터
// 서명 완료 후 처리 로직 작성
});Export API로 데이터 수신
서명자가 서명을 완료하면, 1단계에서 설정한 export_api_info.url로 서명 결과 데이터가 자동으로 전송됩니다.
api_type설정에 따라 수신 시점이 달라집니다
StartAndEnd— 문서 시작 시와 모든 서명 완료 시, 총 2번 수신합니다.ALL— 각 서명자가 서명할 때마다 수신합니다. 다단계 서명에서 중간 진행 상황을 추적할 때 유용합니다.
Export API 이력 조회 및 재전송은 Export API 연동 가이드를 참고하시기 바랍니다.
주의사항
API 호출은 반드시 서버 사이드에서 하시기 바랍니다
access_token은 민감한 인증 정보입니다. 브라우저 클라이언트에서 직접 API를 호출하면 토큰이 노출될 수 있습니다.
반드시 서버에서 API를 호출하고, 클라이언트에는token또는sign_url만 전달하시기 바랍니다.
❌ 브라우저(JS) → eSignon API 직접 호출
✅ 브라우저(JS) → 고객사 서버 → eSignon API 호출 → token 반환 → 브라우저에서 서명 창 열기
샘플 코드
전체 흐름을 한 번에 실행할 수 있는 JavaScript 샘플 코드입니다.
startEsignonEmbed() 함수를 호출하면 토큰 발급 → 문서 시작 → 서명 창 열기까지 자동으로 진행됩니다.
// =============================================
// eSignon 임베디드 연동 샘플 코드
// =============================================
const ESIGNON_DOMAIN = "https://docs.esignon.net";
// -----------------------------------------------
// 1. 인증 토큰 발급
// -----------------------------------------------
async function getAccessToken(companyId, email, password) {
const response = await fetch(`${ESIGNON_DOMAIN}/api/${companyId}/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
header: { request_code: "1001Q" },
body: {
memb_email: email,
memb_pwd: password,
},
}),
});
const data = await response.json();
if (data.header.result_code !== "00") {
throw new Error(data.header.result_msg);
}
return data.body.access_token;
}
// -----------------------------------------------
// 2. 비대면 문서 시작 (임베디드)
// -----------------------------------------------
async function startWorkflow(accessToken, { workflowName, templateId, recipient, fieldList }) {
const response = await fetch(`${ESIGNON_DOMAIN}/api/v3/workflows/start`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `esignon ${accessToken}`,
},
body: JSON.stringify({
workflow_name: workflowName,
template_id: templateId,
recipient_list: [
{ order: 1, name: recipient.name, email: recipient.email }
],
field_list: fieldList || [],
export_api_info: {
url: "https://your-server.com/esignon/webhook", // 서명 완료 데이터 수신 URL
api_type: "StartAndEnd",
is_embed: true,
link_type: "viewer"
}
}),
});
const data = await response.json();
return data; // token, sign_url 포함
}
// -----------------------------------------------
// 3. 서명 창 열기
// -----------------------------------------------
function openSignWindow(companyId, token) {
const signUrl = `${ESIGNON_DOMAIN}/api/${companyId}/sign?token=${token}`
+ `&callback_fn=true` // 서명 완료 후 부모 페이지로 콜백 이벤트 전달
+ `&next_sign=false` // 완료 팝업에서 "다음 문서 작성하기" 버튼 숨기기
+ `&lang=ko`;
const popup = window.open(signUrl, "_blank", "width=1200,height=800,top=100,left=100");
if (!popup) {
alert("팝업이 차단되었습니다. 팝업 허용 후 다시 시도해 주세요.");
}
}
// -----------------------------------------------
// 4. 서명 완료 콜백 수신
// -----------------------------------------------
window.addEventListener("message", function (e) {
console.log("서명 완료 콜백:", e.data);
// 서명 완료 후 처리 로직 작성
});
// -----------------------------------------------
// 전체 흐름 실행 예시
// -----------------------------------------------
async function startEsignonEmbed() {
try {
const companyId = "testapi2";
const email = "[email protected]";
const password = "yourPassword";
// 1. 토큰 발급
const accessToken = await getAccessToken(companyId, email, password);
// 2. 문서 시작
const result = await startWorkflow(accessToken, {
workflowName: "2026_개인정보동의서_홍길동",
templateId: 753,
recipient: { name: "홍길동", email: "010-1234-5678" },
fieldList: [
{ name: "이름", value: "홍길동" },
{ name: "개인정보동의", value: "true" }
]
});
// 3. 서명 창 열기
openSignWindow(companyId, result.token);
} catch (error) {
console.error("오류 발생:", error);
alert(error.message || "오류가 발생했습니다.");
}
}

