documenso-core-workflow-a
Implement Documenso document creation and recipient management workflows. Use when creating documents, managing recipients, adding signature fields, or building signing workflows with Documenso. Trigger with phrases like "documenso document", "create document", "add recipient", "documenso signer", "signature field".
What this skill does
# Documenso Core Workflow A: Document Creation & Recipients
## Overview
Complete workflow for creating documents, managing recipients with different roles, positioning fields, and controlling signing order. Covers both the SDK and v1 REST API for document-centric operations.
## Prerequisites
- Completed `documenso-install-auth` setup
- Understanding of `documenso-sdk-patterns`
- PDF file ready for signing
## Instructions
### Step 1: Create a Document with the SDK
```typescript
import { Documenso } from "@documenso/sdk-typescript";
import { readFileSync } from "fs";
const client = new Documenso({ apiKey: process.env.DOCUMENSO_API_KEY! });
// Create document shell
const doc = await client.documents.createV0({
title: "Service Agreement — Q1 2026",
});
// Upload PDF
const pdf = readFileSync("./contracts/service-agreement.pdf");
await client.documents.setFileV0(doc.documentId, {
file: new Blob([pdf], { type: "application/pdf" }),
});
```
### Step 2: Recipient Roles
Documenso supports these recipient roles:
| Role | Behavior |
|------|----------|
| `SIGNER` | Must complete all assigned fields to finish |
| `VIEWER` | Receives a copy but takes no action |
| `APPROVER` | Must approve before signers can proceed |
| `CC` | Receives a completed copy after all signatures |
```typescript
// Add multiple recipients with roles
const signer = await client.documentsRecipients.createV0(doc.documentId, {
email: "[email protected]",
name: "Alice CEO",
role: "SIGNER",
});
const approver = await client.documentsRecipients.createV0(doc.documentId, {
email: "[email protected]",
name: "Legal Team",
role: "APPROVER",
});
const cc = await client.documentsRecipients.createV0(doc.documentId, {
email: "[email protected]",
name: "Records",
role: "CC",
});
```
### Step 3: Signing Order
Control the sequence in which recipients act. Lower numbers go first.
```typescript
// Sequential signing: legal approves, then CEO signs
await client.documentsRecipients.createV0(doc.documentId, {
email: "[email protected]",
name: "Legal",
role: "APPROVER",
signingOrder: 1, // Goes first
});
await client.documentsRecipients.createV0(doc.documentId, {
email: "[email protected]",
name: "CEO",
role: "SIGNER",
signingOrder: 2, // Goes after legal approves
});
```
### Step 4: Add Fields to Document
Field coordinates use **percentage-based positioning** (0-100 for both X and Y axes). The origin is the top-left corner of the page.
```typescript
// Signature field — bottom of page 1
await client.documentsFields.createV0(doc.documentId, {
recipientId: signer.recipientId,
type: "SIGNATURE",
pageNumber: 1,
pageX: 10, // 10% from left
pageY: 85, // 85% from top
pageWidth: 30, // 30% of page width
pageHeight: 5, // 5% of page height
});
// Date field — next to signature
await client.documentsFields.createV0(doc.documentId, {
recipientId: signer.recipientId,
type: "DATE",
pageNumber: 1,
pageX: 60,
pageY: 85,
pageWidth: 20,
pageHeight: 3,
});
// Name field — auto-filled from recipient
await client.documentsFields.createV0(doc.documentId, {
recipientId: signer.recipientId,
type: "NAME",
pageNumber: 1,
pageX: 10,
pageY: 78,
pageWidth: 30,
pageHeight: 3,
});
// Text field — custom input (e.g., title/position)
await client.documentsFields.createV0(doc.documentId, {
recipientId: signer.recipientId,
type: "TEXT",
pageNumber: 1,
pageX: 60,
pageY: 78,
pageWidth: 30,
pageHeight: 3,
});
```
### Step 5: Multi-Page Document with Multiple Signers
```typescript
async function createMultiSignerContract(
pdfPath: string,
signers: Array<{ email: string; name: string; signPage: number }>
) {
const client = new Documenso({ apiKey: process.env.DOCUMENSO_API_KEY! });
const doc = await client.documents.createV0({ title: "Multi-Party Agreement" });
const pdf = readFileSync(pdfPath);
await client.documents.setFileV0(doc.documentId, {
file: new Blob([pdf], { type: "application/pdf" }),
});
for (let i = 0; i < signers.length; i++) {
const s = signers[i];
const recip = await client.documentsRecipients.createV0(doc.documentId, {
email: s.email,
name: s.name,
role: "SIGNER",
signingOrder: i + 1,
});
// Each signer gets signature + date on their assigned page
await client.documentsFields.createV0(doc.documentId, {
recipientId: recip.recipientId,
type: "SIGNATURE",
pageNumber: s.signPage,
pageX: 10, pageY: 80, pageWidth: 30, pageHeight: 5,
});
await client.documentsFields.createV0(doc.documentId, {
recipientId: recip.recipientId,
type: "DATE",
pageNumber: s.signPage,
pageX: 60, pageY: 80, pageWidth: 20, pageHeight: 3,
});
}
await client.documents.sendV0(doc.documentId);
return doc.documentId;
}
```
### Step 6: Document Metadata and Settings
```typescript
// v1 REST API: create document with metadata
const res = await fetch("https://app.documenso.com/api/v1/documents", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DOCUMENSO_API_KEY}`,
},
body: (() => {
const form = new FormData();
form.append("title", "NDA — Confidential");
form.append("file", new Blob([pdf], { type: "application/pdf" }));
return form;
})(),
});
const document = await res.json();
```
### Step 7: Query and Filter Documents
```typescript
// List documents with pagination
const { documents } = await client.documents.findV0({
page: 1,
perPage: 20,
orderByColumn: "createdAt",
orderByDirection: "desc",
});
// Get single document with all details
const detail = await client.documents.getV0(documentId);
console.log(`Status: ${detail.status}`); // DRAFT | PENDING | COMPLETED
console.log(`Recipients: ${detail.recipients.length}`);
console.log(`Fields: ${detail.fields.length}`);
```
## Document Status Flow
```
DRAFT ──send()──→ PENDING ──all sign──→ COMPLETED
│
├──reject()──→ REJECTED
└──cancel()──→ CANCELLED
```
Only `DRAFT` documents can be modified (add recipients, fields, change PDF).
## Error Handling
| Error | HTTP | Cause | Solution |
|-------|------|-------|----------|
| Document not found | 404 | Invalid document ID | Verify ID with `findV0()` |
| Recipient exists | 400 | Duplicate email on same doc | Update existing with `updateV0()` |
| Invalid field position | 400 | pageX/pageY > 100 or < 0 | Use percentage values 0-100 |
| Cannot modify sent doc | 400 | Document status is PENDING | Create new document or cancel first |
| File too large | 413 | PDF exceeds plan limit | Compress PDF (plan limits vary) |
## Resources
- [Documents API (SDK)](https://github.com/documenso/sdk-typescript/blob/main/docs/sdks/documents/README.md)
- [Recipients API (SDK)](https://github.com/documenso/sdk-typescript/blob/main/docs/sdks/documentsrecipients/README.md)
- [Fields API (SDK)](https://github.com/documenso/sdk-typescript/blob/main/docs/sdks/documentsfields/README.md)
- [Field Types](https://docs.documenso.com/users/documents/fields)
## Next Steps
For template-based workflows and direct signing links, see `documenso-core-workflow-b`.
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.