| name | documenso-upgrade-migration |
| description | Execute Documenso API version upgrades and SDK migrations.
Use when upgrading from v1 to v2 API, updating SDK versions,
or migrating between Documenso versions.
Trigger with phrases like "documenso upgrade", "documenso v2 migration",
"update documenso SDK", "documenso API version".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*) |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Documenso Upgrade & Migration
Overview
Guide for upgrading Documenso SDK versions and migrating from API v1 to v2.
Prerequisites
- Current Documenso integration working
- Test environment available
- Feature flag system (recommended)
- Backup/rollback plan
API Version Differences
v1 vs v2 Comparison
| Feature | API v1 | API v2 |
|---|
| Status | Deprecated | Current |
| SDK Support | Limited | Full TypeScript/Python/Go |
| Documents | /api/v1/documents | /api/v2/documents |
| Templates | /api/v1/templates | /api/v2/templates |
| Envelopes | N/A | /api/v2/envelopes (new) |
| ID Format | Numeric | Prefixed (doc_, tmpl_, etc.) |
| Batch Operations | No | Yes |
| File Streaming | No | Yes |
Migration Steps
Step 1: Update SDK
npm uninstall your-documenso-v1-wrapper
npm install @documenso/sdk-typescript
pip install --upgrade documenso_sdk
Step 2: Update Import Statements
import { DocumensoClient } from "documenso-v1";
import { Documenso } from "@documenso/sdk-typescript";
Step 3: Update Client Initialization
const client = new DocumensoClient({
apiKey: process.env.DOCUMENSO_API_KEY,
baseUrl: "https://app.documenso.com/api/v1",
});
const client = new Documenso({
apiKey: process.env.DOCUMENSO_API_KEY ?? "",
serverURL: "https://app.documenso.com/api/v2/",
});
Step 4: Update Document Operations
const document = await client.documents.create({
title: "My Document",
file: fileBuffer,
});
const docId = document.id;
const document = await client.documents.createV0({
title: "My Document",
file: pdfBlob,
});
const docId = document.documentId;
Step 5: Update Recipient Operations
await client.documents.addRecipient(docId, {
email: "signer@example.com",
name: "John Doe",
role: "signer",
});
await client.documentsRecipients.createV0({
documentId: docId,
email: "signer@example.com",
name: "John Doe",
role: "SIGNER",
});
Step 6: Update Field Operations
await client.documents.addField(docId, recipientId, {
type: "signature",
page: 1,
x: 100,
y: 600,
width: 200,
height: 60,
});
await client.documentsFields.createV0({
documentId: docId,
recipientId: recipientId,
type: "SIGNATURE",
page: 1,
positionX: 100,
positionY: 600,
width: 200,
height: 60,
});
Step 7: Update Template Usage
const doc = await client.templates.createDocument(templateId, {
recipients: [{ email: "signer@example.com", name: "John" }],
});
const envelope = await client.envelopes.useV0({
templateId: templateId,
recipients: [
{
email: "signer@example.com",
name: "John",
signerIndex: 0,
},
],
});
Step 8: Update Webhook Handlers
interface V1WebhookPayload {
type: string;
document: {
id: number;
title: string;
status: string;
};
}
interface V2WebhookPayload {
event: string;
payload: {
id: string;
title: string;
status: string;
recipients: Array<{
email: string;
signingStatus: string;
}>;
};
createdAt: string;
webhookEndpoint: string;
}
app.post("/webhooks/documenso", (req, res) => {
const { event, payload } = req.body as V2WebhookPayload;
switch (event) {
case "document.completed":
handleDocumentCompleted(payload);
break;
case "document.signed":
handleDocumentSigned(payload);
;
}
res.({ : });
});
Gradual Migration Strategy
Step 1: Feature Flag Setup
import { getDocumenso } from "./documenso-v2";
import { getLegacyClient } from "./documenso-v1";
async function getClient() {
const useV2 = await featureFlags.isEnabled("documenso_v2");
if (useV2) {
return { client: getDocumenso(), version: "v2" };
} else {
return { client: getLegacyClient(), version: "v1" };
}
}
Step 2: Adapter Pattern
interface DocumentService {
createDocument(title: string, file: Blob): Promise<{ id: string }>;
addRecipient(docId: string, email: string, name: string): Promise<void>;
sendDocument(docId: string): Promise<void>;
}
class V1DocumentService implements DocumentService {
async createDocument(title: string, file: Blob) {
const doc = await v1Client.documents.create({ title, file });
return { id: String(doc.id) };
}
}
class V2DocumentService implements DocumentService {
() {
doc = v2Client..({ title, file });
{ : doc.! };
}
}
(): {
featureFlags.()
? ()
: ();
}
Step 3: Migration Rollout
Week 1: Deploy v2 code with feature flag OFF
Week 2: Enable v2 for internal users (5%)
Week 3: Enable v2 for beta users (20%)
Week 4: Enable v2 for all users (100%)
Week 5: Remove v1 code
ID Migration
If you store document IDs in your database:
async function migrateDocumentIds() {
const documents = await db.documents.findAll({
where: { documensoId: { notLike: 'doc_%' } }
});
for (const doc of documents) {
console.log(`Migrate: ${doc.documensoId} -> doc_xxx`);
}
}
Testing Migration
async function testMigration(testData: TestDocument) {
const v1Result = await v1Service.createDocument(testData);
const v2Result = await v2Service.createDocument(testData);
assert(v2Result.status === v1Result.status);
assert(v2Result.recipients.length === v1Result.recipients.length);
console.log("Migration test passed");
}
Rollback Plan
featureFlags.disable("documenso_v2")
kubectl rollout undo deployment/signing-service
Output
- Updated SDK to latest version
- Migrated from v1 to v2 API
- Feature flags controlling rollout
- Rollback procedure ready
Error Handling
| Issue | Cause | Solution |
|---|
| ID mismatch | v1 vs v2 format | Use adapter to normalize |
| Missing field | API change | Update to new field names |
| 404 on template | ID format changed | Fetch new template ID |
| Enum errors | Case sensitivity | Use uppercase enums |
Resources
Next Steps
For CI/CD integration, see documenso-ci-integration.