Document templates and signatures
Create an e-signature template from a vault file, open a signature request for a payee, collect signing URLs, and track signing to completion.
A document template turns a vault file into something that can be signed. A signature request opens that template for one payer-payee relationship. The Payee signs first, then the payer countersigns when the template asks for it.
Read Compliance and verification first for the payer and payee rules shared by order-style resources. Requirements and eligibility shows a full NDA example.
Before you start
- The document is in the vault with
kind: Document. See Vault files. - Scopes:
signed-documents.signed-document-template:readand:writefor templates,signed-documents.signed-document:readand:writefor requests.
Endpoints
1. Create a template
| Field | Type | Notes |
|---|---|---|
title | string, required | |
fileId | string, required | The vault file. Create-only. |
signerRoles | array, required | Any of Payer, Payee. Create-only. |
externalId | string | A duplicate returns 409. |
metadata | object |
curl -X POST https://api.wingspan.app/v3/compliance/document-templates \
-H "Authorization: Bearer $WINGSPAN_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "title": "Northwind NDA 2026", "fileId": "VAULT_FILE_ID", "signerRoles": ["Payee"] }'The template is created on the e-signature provider from fileId. The response has status: Active and an editUrl into the provider's embedded editor, where you place signature and merge fields. editUrl and viewUrl expire (editUrlExpiresAt, viewUrlExpiresAt). GET .../{templateId} refreshes both. List rows carry the stored editUrl, which may be expired, and no viewUrl.
The id is what a Signature requirement definition passes as dataSourceId.
To retire a template, PATCH it with status: Inactive. A requirement definition already bound to it keeps resolving it. DELETE removes it on the provider as well and can't be undone. It returns 409 once any signature request has been opened against it, signed or not. PATCH can also change title, externalId, and metadata, but not fileId or signerRoles. A template owned by another account returns 404.
2. Open a signature request
POST /v3/compliance/signature-requests:
| Field | Type | Notes |
|---|---|---|
payerPayeeId | string, required | The relationship. |
templateId | string | Payer only. |
requirementId | string | Required for a payee. |
externalId | string | Payer only. |
metadata | object | Payer only. |
The title and signer roles come from the template. This opens the request but doesn't send it. A 201 doesn't mean a new request: when a repeat is deduplicated, you get the outstanding one back unchanged, and metadata from the repeat isn't applied. Send an externalId to force a distinct request. There's no flag that says created or found. Compare events.createdAt if you need to tell.
curl -X POST https://api.wingspan.app/v3/compliance/signature-requests \
-H "Authorization: Bearer $WINGSPAN_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{ "payerPayeeId": "PAYER_PAYEE_ID", "templateId": "TEMPLATE_ID" }'// 201 Created (trimmed)
{
"id": "REQUEST_ID",
"templateId": "TEMPLATE_ID",
"status": "New",
"title": "Northwind NDA 2026",
"signers": []
}3. Sign
- The Payee calls
POST .../{requestId}/start. It prepares the document with the provider and returns signing URLs. It is the only call that moves a request out ofNew. It is safe to call again: a prepared request isn't prepared twice, and the URLs come back either way. A payer who callsstartprepares nothing and gets an emptysignersarray. - The payee opens its
signingUrl. - After the payee signs, the payer countersigns. The payer calls
GET .../{requestId}/signing-urlsfor its link. Payer links need countersign permission.
// 200 OK
{
"signers": [
{
"accountId": "PAYEE_ACCOUNT_ID",
"role": "Payee",
"email": "[email protected]",
"signingUrl": "https://sign.example.com/...",
"expiresAt": "2026-11-02T17:45:00Z"
}
]
}Signing URLs are single use and expire within the hour. Don't store them. Call start or signing-urls again for a fresh one. Before start runs on a request opened by a requirement, signing-urls returns an empty list.
POST .../{requestId}/remind sends a reminder to signers who haven't signed. POST .../{requestId}/cancel cancels a pending request. Both can return 409.
Status
New to AwaitingSignature (a document exists, nobody has signed) to AwaitingCountersignature (the payee signed) to Completed. Each signers entry has accountId, role, email, status (Pending or Signed), signedAt, and order. There is no declined state. The request has completedFileId once signed, and events with payeeSignedAt, payerSignedAt, and completedAt.
GET .../{requestId} refreshes status from the provider, so it can take a round trip and returns 503 when the provider is unavailable. responseItems (the values entered in the signed document's fields) are visible only to the payer. A payee gets an empty array. List rows omit responseItems.
List filters: status, payeeAccountId, templateId, externalId (each eq or anyOf), and accountIds[anyOf].
Render a template into a vault file
POST /v3/compliance/document-templates/{templateId}/vault-files renders the template into a vault file and can open a signature request against the result. Body fields: fieldValues (merged into the template), title, documentType, payeeId, signatureRequest, and metadata.
One-off requests from a vault file
POST /v3/compliance/vault-files/{fileId}/signature-requests opens a request with its own signer list, using the path's file as the unsigned source. signers is required, and each signer has role, name, and optionally accountId and email. Optional: templateId, title, message, payeeId, metadata. To authorize a request through a requirement, use POST /v3/compliance/signature-requests instead.
Errors
| Status | When |
|---|---|
400 | A payee created a request without requirementId. Checked first. |
404 | No seat on payerPayeeId. A template owned by another account. A payee calls PATCH on a request. |
409 | Duplicate externalId. DELETE on a template that has requests. |
422 | A payee sent templateId, externalId, or metadata with requirementId. |
503 | The e-signature provider is unavailable on a read. |
Events
DocumentTemplate.Created, SignatureRequest.Created, Sent, Reminded, Completed, Cancelled.
Updated 12 minutes ago