콘텐츠로 이동

봉투와 수신자

봉투는 서명을 향해 진행 중인 하나의 계약입니다. 변수를 넣어 렌더링한 템플릿 버전, 그 위에서 작업하는 수신자, 그리고 일어난 모든 일의 증거로 구성됩니다. POST /v1/envelopes로 만듭니다.

필드 유형 설명
template tpl_… 필수
version 숫자 또는 "latest" 기본값은 latest. 생성 시 확정되어 고정됩니다. 게시된 버전이어야 합니다
variables 객체 버전의 JSON Schema에 따라 검증됩니다
recipients 배열 역할별 한 명(role, name, email. 선택적으로 externalUserId, verification, 필드 ID별 미리 채우기 값 fields, 서명 순서를 변경하는 order)
subject, message 문자열 서명 요청 이메일에 사용되고 서명 페이지에 표시됩니다
delivery email · embedded · none 기본값은 email
expiresAt RFC 3339 미래 시점이어야 합니다. 그 시점에 봉투가 만료되며 서명 링크와 열람자 링크가 더 이상 작동하지 않습니다
cc 배열 템플릿의 CC 역할 외에 추가하는 CC 수신자(name, email). 최대 50명
viewers 배열 서명하지 않고 봉투의 진행 상황을 지켜보는 사람(name, email, 선택적으로 notifyOnSignature). 봉투당 인원은 플랜에 따라 제한됩니다
viewerDocumentAccess 불리언 열람자가 상태 페이지에서 문서를 열 수 있게 합니다. 기본값은 false(상태만 표시). Team 플랜 이상
reminders 객체 { "enabled": false }는 알림을 끄고, { "enabled": true, "intervalHours": 24 }는 간격(1~720)을 변경합니다
externalId 문자열 자체 ID. 최대 200자
dedupeOn "external_id" 새로 만드는 대신 이 externalId를 가진 기존 봉투를 반환합니다
metadata 문자열 값 객체 값당 최대 500자. 봉투와 웹훅에 함께 반환됩니다

모든 수신자에게는 해당 버전의 역할이 필요하며, CC가 아닌 각 역할에는 수신자가 정확히 한 명 있어야 합니다. 오류는 /recipients/1/role이나 /recipients/0/fields/start_date 같은 포인터와 함께 한꺼번에 보고됩니다.

응답: 봉투와 Location 헤더를 포함한 201. dedupeOn이 일치하면 기존 봉투와 x-deduplicated: true를 포함한 200. ?dry_run=true이면 드라이 런 요약을 포함한 200. Free 워크스페이스가 포함된 봉투를 모두 사용했으면 402. 열람자가 플랜 허용량을 초과하거나 viewerDocumentAccess가 플랜에 포함되지 않으면 403 plan-upgrade-required(플랜 및 한도). 드라이 런도 플랜 한도를 확인합니다.

최초 릴리스 이후에 추가된 필드는 모두 선택 사항입니다. 이 필드가 없는 요청은 이전과 똑같이 동작합니다.

누가 어떤 순서로 서명할지는 템플릿에서 정의합니다. 봉투 하나에 대해서는 템플릿을 건드리지 않고 이를 변경할 수 있습니다.

{
"template": "tpl_9fK2mQ7xLp",
"variables": { "client": { "name": "Jane Doe" } },
"recipients": [
{ "role": "client", "name": "Jane Doe", "email": "jane@acme.dev", "order": 2 },
{ "role": "company", "name": "Sam Lee", "email": "sam@bonafide.dev", "order": 1 },
{ "role": "witness", "name": "Kim Park", "email": "kim@acme.dev", "order": 1 }
],
"cc": [{ "name": "Legal", "email": "legal@acme.dev" }],
"viewers": [{ "name": "Alex Chen", "email": "alex@acme.dev", "notifyOnSignature": true }],
"reminders": { "enabled": true, "intervalHours": 48 },
"expiresAt": "2026-11-30T23:59:59Z"
}
  • 순서: recipients[].order는 수신자가 서명하는 단계입니다. 같은 번호의 수신자는 동시에 서명합니다. 지정하지 않으면 템플릿에 있는 역할의 order가 적용됩니다. 순서는 양의 정수이며, CC 역할에는 순서를 지정할 수 없습니다. 모든 역할에는 여전히 수신자가 필요하고(템플릿의 필드가 서명자를 유지하도록), 적어도 한 명의 수신자는 서명해야 합니다. envelope.created 이벤트에는 routingOverridden: true가 기록됩니다.
  • CC: 추가 CC 수신자는 완료된 문서 이메일을 받으며 서명하지 않습니다. 이들은 recipients에 kind: "cc", 역할 _cc로 표시됩니다.
  • 알림: 차례가 된 사람에게 intervalHours마다(기본값: 배포 환경의 REMINDER_INTERVAL_HOURS, 72) 최대 세 번 알림을 보냅니다. enabled: false이면 보내지 않습니다. 알림은 email 전달에 적용됩니다.
  • 서명자 인증은 수신자별로 설정합니다. verification이 역할의 방식보다 우선합니다. 현재 none(고유한 서명 링크만 사용하며, 방식을 지정하지 않은 역할의 기본값)과 email_otp(링크와 이메일로 받는 코드)를 사용할 수 있으며, passkey와 id_check는 아직 지원되지 않아 거부됩니다. 서명자 인증을 참조하세요.
  • 언어: 수신자, CC, 열람자의 locale(또는 자체 값이 없는 모든 사람을 위해 봉투에 지정한 같은 필드)은 서명 페이지와 이메일의 언어를 설정하며, 50개 서명 언어 중 하나여야 합니다. 지정하지 않으면 서명 페이지는 브라우저 언어를 따르고 이메일은 영어로 전송됩니다.

대시보드의 발송 화면에서도 같은 옵션을 제공합니다. 단계를 앞뒤로 옮기고, 동시에 서명을 선택하고, CC와 열람자를 추가하고, 각 서명자의 인증 방식(이메일 링크만 또는 이메일 링크 + 코드)과 언어를 고르고, 만료일과 알림 일정을 설정할 수 있습니다.

  • email: 각 수신자의 차례가 되면 호스팅 서명 페이지 링크를 이메일로 보냅니다. 서명하지 않은 수신자에게는 며칠마다(최대 세 번) 알림이 전송되며, 봉투가 완료되면 모두에게 이메일이 전송됩니다.
  • embedded: 서명자에게 이메일을 보내지 않습니다. 서명자가 자사 제품에 있을 때 서명 세션을 발급하세요. 열람자에게는 여전히 상태 링크가 이메일로 전송됩니다.
  • none: 이메일을 전혀 보내지 않습니다(열람자 포함). 링크를 직접 전달하는 경우(호스팅 세션)에 사용합니다.

POST /v1/envelopes/{id}/recipients/{recipient}/resend는 차례가 된 수신자에게 새 링크를 이메일로 보냅니다(최대 1분에 한 번).

┌──────────── declined (a signer declined)
│
sent ─────┼──────────── voided (POST /v1/envelopes/{id}/void)
│
├──────────── expired (expiresAt passed)
│
└──────────── completed ──► seal: pending ──► sealed
status 의미
rendering 준비 중
sent 진행 중: 수신자가 라우팅 순서대로 서명하고 있습니다
completed 모든 수신자가 완료했습니다. 봉인이 시작됩니다
declined 수신자가 거절하여 봉투가 종료되었습니다
voided 봉투를 무효화했습니다({ "reason": "…" }). 열려 있는 서명 세션은 더 이상 작동하지 않습니다
expired 완료되기 전에 expiresAt이 지났습니다

seal은 봉인된 PDF의 상태를 나타냅니다: not_started, pending(완료되어 봉인 중), sealed, failed. 봉인 때문에 완료가 지연되는 일은 없습니다. 봉투가 먼저 완료되고 바로 뒤이어 봉인됩니다.

{
"id": "rcp_5Jw0pLs9Xe",
"role": "client",
"name": "Jane Doe",
"email": "jane@acme.dev",
"order": 1,
"status": "viewed",
"verification": "email_otp",
"completedAt": null
}

수신자의 status는 pending(아직 차례가 아님), sent, viewed, completed, declined 중 하나이고, kind는 역할의 signer, approver, form_filler, cc 중 하나입니다. 라우팅은 order(역할의 순서 또는 발송 시 재정의)를 따릅니다. 완료되지 않은 가장 낮은 순서의 수신자 전원이 동시에 작업하고, 이들이 끝나면 다음 그룹이 시작됩니다. CC 수신자는 라우팅을 막지 않습니다.

열람자는 서명하지 않고 봉투의 진행 상황을 지켜보는 사람입니다. 예를 들어 관리자, 법무 보조원, 고객 측의 계정 담당자 등입니다. 열람자는 수신자가 아닙니다. 역할도 차례도 없으며, 어떤 것도 막거나 완료하지 않고, 인증서의 서명자 목록에도 나타나지 않습니다.

  • 봉투가 발송되면(또는 나중에 POST /v1/envelopes/{id}/viewers로 추가하면) 각 열람자는 읽기 전용 상태 페이지 링크가 담긴 브랜드 이메일을 받습니다. 이 페이지에는 봉투 제목, 발신자, 각 단계와 그 수신자의 이름, 역할, 상태, 타임스탬프가 서명 진행에 따라 실시간으로 표시됩니다. 수신자의 이메일 주소는 표시되지 않습니다.
  • 봉투가 완료, 거절, 무효화되면 열람자에게 다시 이메일이 전송되며, notifyOnSignature가 true이면 서명할 때마다 전송됩니다(기본값은 꺼짐).
  • 문서는 viewerDocumentAccess: true를 설정한 경우(Team 플랜 이상)에만 페이지에 표시됩니다. 진행 중에는 원본이, 봉인된 후에는 봉인된 PDF가 표시됩니다. 그렇지 않으면 열람자에게는 상태만 표시됩니다.
  • DELETE /v1/envelopes/{id}/viewers/{viewer}는 열람자의 접근 권한을 취소합니다. 그 열람자에게 보낸 모든 링크가 즉시 작동을 멈춥니다.
  • 링크는 개인용 권한 URL입니다. 각 링크 토큰의 SHA-256만 저장됩니다. 링크는 봉투가 만료될 때까지 (최대 90일), 그리고 봉투가 종료된 후 30일 동안 작동하며, 열람자의 접근 권한이 취소되면 더 이상 작동하지 않습니다.
  • 추가, 열람(페이지와 문서의 첫 열람), 취소는 감사 추적에 viewer.added, viewer.viewed, viewer.document_viewed, viewer.revoked로 기록되며, 따라서 인증서에도 기록됩니다.

단일 봉투 응답(생성, 조회, 무효화)에는 열람자 목록이 포함됩니다.

{
"viewers": [
{
"id": "vwr_2Hc8sQ1nVt",
"name": "Alex Chen",
"email": "alex@acme.dev",
"notifyOnSignature": true,
"status": "active",
"invitedAt": "2026-10-13T13:58:04.512Z",
"firstViewedAt": "2026-10-13T14:05:41.090Z",
"lastViewedAt": "2026-10-13T15:12:09.337Z",
"revokedAt": null,
"createdAt": "2026-10-13T13:58:04.512Z"
}
],
"viewerDocumentAccess": false
}

봉투당 열람자 수는 플랜에 따라 다릅니다(Free 1명, Pay-as-you-go 2명, Team 5명, Business 20명, Platform 무제한). CC 수신자는 포함되지 않습니다. 접근 권한이 취소된 열람자의 자리는 비워집니다.

GET /v1/envelopes/{id}/document?version=…은 PDF를 다운로드하며, 그 SHA-256을 x-document-sha256으로 함께 반환합니다.

version 파일
original(기본값) 서명을 위해 발송된, 렌더링된 문서
sealed 최종 PDF: 값이 평탄화되고, 완료 인증서가 덧붙여지고, 문서 타임스탬프가 적용된 파일. envelope.sealed 이후에 제공
certificate 완료 인증서만

봉투의 documentHash는 원본의 SHA-256이고 sealedDocumentHash는 봉인된 파일의 SHA-256입니다. 검증에서는 이 값들을 조회합니다.

모든 작업은 봉투별 해시 체인의 이벤트로 기록됩니다: hash = SHA-256(prevHash ‖ canonical JSON of the event). 첫 번째 prevHash는 0이 64개입니다. GET /v1/envelopes/{id}/events는 이벤트를 반환하고 체인을 검사합니다.

{
"data": [
{
"id": "evt_…",
"envelope": "env_8Gm2kQ4rT1",
"seq": 1,
"type": "envelope.created",
"createdAt": "2026-10-13T13:58:04.512Z",
"recipient": null,
"actor": { "kind": "api_key", "id": "…", "name": null, "email": null },
"ip": "203.0.113.7",
"userAgent": null,
"data": { "template": "tpl_…", "templateVersion": 3, "documentHash": "9f2c…" },
"hash": "4b1d…",
"prevHash": "0000000000000000000000000000000000000000000000000000000000000000"
}
],
"chain": { "valid": true, "brokenAt": null }
}

감사 추적에는 웹훅 이벤트 유형 외에도 감사 전용 항목이 있습니다. 예를 들어 session.created, recipient.verified, recipient.reminded, 그리고 열람자 이벤트(열람자가 페이지를 열면 actor kind는 viewer)입니다.

UI에 실시간 상태를 표시하려면 GET /v1/envelopes/{id}/events/stream을 사용하세요. 이는 서버 전송 이벤트(SSE) 스트림으로, 각 프레임의 이벤트 이름은 이벤트의 type, ID는 seq입니다. 이어서 받으려면 Last-Event-ID로 다시 연결하세요.

GET /v1/envelopes는 status, seal, template, q(수신자 이름과 이메일, externalId, 봉투 ID를 대상으로 하는 자유 텍스트)로 필터링합니다. 다른 모든 목록과 마찬가지로 커서 기반 페이지네이션을 사용합니다.

{ "data": [ … ], "hasMore": true, "nextCursor": "…" }

nextCursor를 cursor로 다시 전달하세요. limit는 1~100(기본값 20)입니다.