콘텐츠로 이동

템플릿, 역할 및 필드

템플릿은 재사용할 수 있는 계약서입니다. 이름, 하나의 초안, 그리고 원하는 수만큼의 게시된 버전을 가집니다. 봉투는 항상 게시된 버전으로 만들어지며, 게시된 버전은 변경할 수 없습니다. 템플릿을 편집한다는 것은 새 초안을 저장하고 다음 버전으로 게시한다는 뜻입니다. 이미 발송된 봉투는 고정한 버전을 계속 사용합니다.

GET /v1/templates/tpl_…
{
"id": "tpl_3kQ9xV2mLp",
"organization": "org_…",
"name": "Mutual NDA",
"description": "Two-party NDA, US law",
"latestVersion": 3,
"draftVersion": 4,
"createdAt": "2026-10-01T09:12:44.120Z",
"updatedAt": "2026-10-12T16:03:10.981Z"
}

ID는 접두사가 붙은 문자열입니다(tpl_, tplv_, tfl_, env_, rcp_, ses_, lnk_, evt_, whk_, whd_ 등). 타임스탬프는 UTC 기준 RFC 3339 형식입니다.

오버레이 모드(source: "pdf")는 업로드한 문서에서 시작합니다. 필드는 페이지 위에 놓이는 사각형으로, PDF 포인트(1/72인치) 단위이며 원점은 페이지 왼쪽 위, 페이지 인덱스는 0부터 시작합니다. 업로드한 .docx는 한 번만 PDF로 변환되며(LibreOffice를 사용해 Word 레이아웃을 유지합니다. 파일에 포함되지 않은 글꼴은 대체될 수 있습니다), 그 이후에는 다른 PDF와 똑같이 취급됩니다. 파일에는 convertedFrom: "docx"가 표시됩니다. 오버레이 버전에는 콘텐츠 편집(제자리 텍스트 편집, 화이트아웃, 텍스트 상자, 이미지, 페이지 작업)도 포함할 수 있으며, 버전을 게시할 때 적용됩니다.

문서 모드(source: "document")는 계약서 자체를 서식 있는 텍스트(ProseMirror JSON)로 저장하며, {{client.name}} 같은 변수 칩, 인라인 필드 블록, 조건부 섹션(showIf 식이 참일 때만 유지), 반복 섹션과 표 행(배열 변수의 항목마다 하나씩)을 포함합니다. 각 봉투는 자체 PDF를 렌더링하며, 필드 위치는 그 렌더링 결과에서 읽어 옵니다. 대시보드에서 문서 모드는 “빈 문서로 시작”입니다. API에서는 POST /v1/templates/{id}/import로 Word 파일을 문서 모드로 가져올 수도 있습니다. {{tags}}는 변수나 필드가 되고, 서명란 (“Signature: ____”, “By: ____”, “Date: ____”)은 필드 블록이 됩니다.

새 템플릿에서는 두 가지 시작 방법을 제공합니다.

  • 문서 업로드: 최대 25 MB의 .pdf 및 .docx 파일을 받는 하나의 드롭 영역입니다. Word 파일은 PDF로 변환되어 디자이너에서 열리며, 필드를 배치하기 전에 변환된 레이아웃을 확인하라는 안내가 표시됩니다. 작은 수정은 PDF에서 바로 할 수 있고(“콘텐츠 편집”), 대폭 고쳐 쓰려면 Word 파일을 수정한 다음 다시 업로드하세요.
  • 빈 문서로 시작: 문서 모드에서 계약서를 작성합니다.

디자이너의 콘텐츠 편집 모드에서는 업로드한 파일을 건드리지 않고 서명자에게 보이는 내용을 변경합니다. 기본 도구인 텍스트 편집은 페이지의 텍스트 블록(PDF의 텍스트 레이어에서 묶은 줄과 단락)을 강조 표시합니다. 블록을 클릭하거나 Tab 키로 이동해 Enter 키를 누르면 같은 위치, 크기, 색상, 정렬, 글꼴 그대로 제자리에서 편집할 수 있습니다. Ctrl/Cmd+Enter로 저장하고 Esc로 취소하며, 각 편집은 편집 목록에서 되돌릴 수 있습니다. 편집은 다른 변경과 마찬가지로 실행 취소할 수 있습니다. 다른 도구로는 화이트아웃, 텍스트 상자, 이미지를 추가하고, 페이지를 삽입, 삭제, 재정렬, 회전할 수 있습니다.

제자리 텍스트 편집은 group을 공유하는 두 항목으로 저장됩니다. 원래 블록을 (페이지 배경색으로) 덮는 화이트아웃과, 블록 안에 배치되는 텍스트 항목이며, 텍스트 항목은 블록의 줄 높이와 첫 번째 기준선을 따릅니다.

edits.items (excerpt)
[
{ "id": "whiteout_k2", "kind": "whiteout", "group": "blk_k1", "page": 0, "color": "#FFFFFF",
"rect": { "x": 71, "y": 209.9, "width": 452, "height": 26.9 } },
{ "id": "text_k3", "kind": "text", "group": "blk_k1", "page": 0, "rect": { "x": 72, "y": 210.9, "width": 451, "height": 24.9 },
"text": "1. Purpose. The Parties wish to evaluate a joint venture…", "original": "1. Purpose. The Parties wish to evaluate a possible business relationship…",
"size": 10.5, "lineHeight": 15.23, "baseline": 7.54, "padding": 0, "align": "left", "color": "#0B0F1A",
"face": { "source": "pdf", "name": "ABCDEF+Calibri", "fallback": "carlito" }, "font": "helvetica" }
]

face는 글꼴을 선택합니다. 새 텍스트의 모든 문자를 그릴 수 있으면 PDF에 포함된 글꼴을 사용하고, 그렇지 않으면 번들로 제공되는 메트릭 호환 글꼴(Helvetica/Arial에는 sans Arimo, Times에는 serif Tinos, Courier에는 mono Cousine, Calibri에는 carlito Carlito)을 같은 굵기와 스타일로 사용합니다. 텍스트는 블록 안에서 줄 바꿈됩니다. 원래보다 더 많은 줄이 필요하면 편집 영역이 아래쪽 빈 공간으로 늘어나며, 빈 공간이 없으면 디자이너가 저장을 거부합니다 (“텍스트가 들어가지 않습니다 — 줄이거나 공간을 추가하세요”). 디자이너와 API는 레이아웃 및 글꼴 코드를 공유하므로, 게시된 PDF는 미리 보기와 한 줄 한 줄 일치합니다.

편집은 초안만 변경할 수 있습니다. 게시하면 편집이 새 기본 PDF에 적용되며, 그 SHA-256이 버전의 documentHash(서명자에게 보이는 내용의 해시)가 됩니다. 업로드한 원본은 버전의 sourceFile로 보관되며, 다음 초안은 같은 편집이 적용된 상태로 그 원본에서 시작합니다. 화이트아웃은 내용을 시각적으로만 가리며, 원래 텍스트는 그 아래 파일 안에 남아 있으므로 안전한 삭제(redaction) 수단이 아닙니다.

역할은 계약의 당사자입니다. 봉투의 수신자는 key로 역할과 연결됩니다.

{ "key": "client", "label": "Client", "kind": "signer", "order": 1, "verification": "none" }
속성 의미
key 필드와 봉투 수신자가 사용하는 소문자 식별자(^[a-z][a-z0-9_]*$)
kind signer(서명 또는 이니셜 필드가 있어야 함), approver, form_filler, 또는 cc(받기만 하고 서명하지 않음)
order 1부터 시작하는 라우팅 순서. 같은 순서의 역할은 동시에 서명하며, 이들이 끝나면 다음 순서가 시작됩니다
verification 역할의 수신자가 본인임을 증명하는 방법: none(기본값: 고유한 서명 링크만 사용) 또는 email_otp(링크와 이메일로 받는 코드). 수신자별로 재정의할 수 있습니다. 서명자 인증을 참조하세요

passkey, id_check, sms_otp는 스키마에 있지만 아직 서명에 사용할 수 없습니다. passkey나 id_check를 사용하는 템플릿은 게시할 수 없으며, SMS 코드는 아직 전송되지 않습니다.

{
"id": "client_signature",
"type": "signature",
"role": "client",
"label": "Signature",
"required": true,
"rect": { "page": 1, "x": 72, "y": 610, "width": 220, "height": 48 }
}

필드 유형: signature, initials, name, email, date_signed, text, number, date, checkbox, radio, dropdown, attachment, formula, stamp, variable_text(서명자가 아니라 발신자가 변수로 채우는 필드). 필드에는 다음 항목도 지정할 수 있습니다.

  • variable: 필드를 바인딩하거나 미리 채우기 위해 변수 안을 가리키는 JSON Pointer(/client/name)
  • options: radio와 dropdown의 선택지
  • validation: pattern, min, max, maxLength, 또는 format(email, phone, date, number, currency)
  • showIf: 변수와 다른 필드에 대한 조건(예: plan != "free")
  • formula: 계산되는 읽기 전용 값
  • overflow: 값이 상자에 들어가지 않을 때의 처리: shrink(기본값), wrap, reject

버전의 variables는 각 봉투와 함께 보내는 데이터의 JSON Schema(draft 2020-12)이며, 버전의 sampleVariables는 그 예시입니다. POST /v1/envelopes는 보낸 variables를 이 스키마로 검증하고 모든 문제를 JSON Pointer와 함께 보고합니다.

{
"type": "https://bonafidesign.com/problems/validation-error",
"title": "Validation failed",
"status": 422,
"detail": "The request is invalid.",
"errors": [
{ "pointer": "/variables/client/name", "message": "is required", "hint": "Provide a value for 'name'." }
]
}

발송하기 전에 결과를 확인하려면 POST /v1/templates/{id}/versions/{version}/render({ "variables": { … } } → PDF)로 원하는 버전의 워터마크가 들어간 미리 보기를 렌더링하거나, ?dry_run=true를 붙여 봉투를 만드세요.

대부분의 팀은 대시보드의 디자이너에서 템플릿을 설계합니다. 디자이너에서 하는 모든 작업은 API로도 할 수 있습니다.

  1. { "name": "Mutual NDA" }로 POST /v1/templates를 호출합니다.
  2. PDF(또는 .docx)를 본문으로(Content-Type: application/pdf) 또는 멀티파트 필드 file로 POST /v1/templates/{id}/files에 보냅니다. 최대 25 MB입니다. 응답에는 파일 ID(tfl_…), 페이지 수, 페이지 크기가 포함됩니다.
  3. roles, fields, variables(그리고 file, 또는 source: "document"와 content)로 PUT /v1/templates/{id}/draft를 호출합니다. 초안은 있는 그대로 저장되며, 이 단계에서는 아무것도 검사하지 않습니다.
  4. POST /v1/templates/{id}/publish를 호출합니다. 게시할 때 초안을 린트합니다. 모든 필드의 역할이 존재하는지, 모든 서명자 역할에 서명 필드가 있는지, 필드가 페이지 안에 들어가는지, 라디오 버튼과 드롭다운 필드에 선택지가 있는지, 식을 파싱할 수 있는지 확인합니다. 문제가 있으면 /fields/3/rect 같은 포인터가 포함된 422가 반환됩니다.
터미널 창
curl https://api.bonafidesign.com/v1/templates/tpl_3kQ9xV2mLp/files \
-H "Authorization: Bearer $BONA_FIDE_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @nda.pdf

버전 엔드포인트는 번호, latest, draft를 받습니다: GET /v1/templates/{id}/versions/latest, GET /v1/templates/{id}/versions/2/document(기본 PDF). 봉투나 서명 링크에서 한 번도 사용되지 않은 템플릿은 삭제할 수 있으며, 그렇지 않으면 DELETE는 409 in-use를 반환합니다.