documenso-sdk-patterns
Apply production-ready Documenso SDK patterns for TypeScript and Python. Use when implementing Documenso integrations, refactoring SDK usage, or establishing team coding standards for Documenso. Trigger with phrases like "documenso SDK patterns", "documenso best practices", "documenso code patterns", "idiomatic documenso".
Best use case
documenso-sdk-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Apply production-ready Documenso SDK patterns for TypeScript and Python. Use when implementing Documenso integrations, refactoring SDK usage, or establishing team coding standards for Documenso. Trigger with phrases like "documenso SDK patterns", "documenso best practices", "documenso code patterns", "idiomatic documenso".
Teams using documenso-sdk-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/documenso-sdk-patterns/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How documenso-sdk-patterns Compares
| Feature / Agent | documenso-sdk-patterns | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Apply production-ready Documenso SDK patterns for TypeScript and Python. Use when implementing Documenso integrations, refactoring SDK usage, or establishing team coding standards for Documenso. Trigger with phrases like "documenso SDK patterns", "documenso best practices", "documenso code patterns", "idiomatic documenso".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# Documenso SDK Patterns
## Overview
Production-ready patterns for the Documenso TypeScript SDK (`@documenso/sdk-typescript`) and Python SDK. Covers singleton clients, typed wrappers, error handling, retry logic, and testing patterns.
## Prerequisites
- Completed `documenso-install-auth` setup
- Familiarity with async/await and TypeScript generics
- Understanding of error handling best practices
## Instructions
### Pattern 1: Singleton Client with Configuration
```typescript
// src/documenso/client.ts
import { Documenso } from "@documenso/sdk-typescript";
interface DocumensoConfig {
apiKey: string;
baseUrl?: string;
timeout?: number;
}
let instance: Documenso | null = null;
export function getDocumensoClient(config?: DocumensoConfig): Documenso {
if (!instance) {
const apiKey = config?.apiKey ?? process.env.DOCUMENSO_API_KEY;
if (!apiKey) throw new Error("DOCUMENSO_API_KEY is required");
instance = new Documenso({
apiKey,
...(config?.baseUrl && { serverURL: config.baseUrl }),
});
}
return instance;
}
// Reset for testing
export function resetClient(): void {
instance = null;
}
```
### Pattern 2: Typed Document Service
```typescript
// src/documenso/documents.ts
import { getDocumensoClient } from "./client";
export interface CreateDocumentInput {
title: string;
pdfPath: string;
signers: Array<{
email: string;
name: string;
fields: Array<{
type: "SIGNATURE" | "INITIALS" | "NAME" | "EMAIL" | "DATE" | "TEXT";
pageNumber: number;
pageX: number;
pageY: number;
pageWidth?: number;
pageHeight?: number;
}>;
}>;
}
export interface DocumentResult {
documentId: number;
recipientIds: number[];
status: "DRAFT" | "PENDING" | "COMPLETED";
}
export async function createAndSendDocument(
input: CreateDocumentInput
): Promise<DocumentResult> {
const client = getDocumensoClient();
const { readFileSync } = await import("fs");
// Create document
const doc = await client.documents.createV0({ title: input.title });
// Upload PDF
const pdfBuffer = readFileSync(input.pdfPath);
await client.documents.setFileV0(doc.documentId, {
file: new Blob([pdfBuffer], { type: "application/pdf" }),
});
// Add recipients and fields
const recipientIds: number[] = [];
for (const signer of input.signers) {
const recipient = await client.documentsRecipients.createV0(doc.documentId, {
email: signer.email,
name: signer.name,
role: "SIGNER",
});
recipientIds.push(recipient.recipientId);
for (const field of signer.fields) {
await client.documentsFields.createV0(doc.documentId, {
recipientId: recipient.recipientId,
type: field.type,
pageNumber: field.pageNumber,
pageX: field.pageX,
pageY: field.pageY,
pageWidth: field.pageWidth ?? 20,
pageHeight: field.pageHeight ?? 5,
});
}
}
// Send
await client.documents.sendV0(doc.documentId);
return { documentId: doc.documentId, recipientIds, status: "PENDING" };
}
```
### Pattern 3: Error Handling Wrapper
```typescript
// src/documenso/errors.ts
export class DocumensoError extends Error {
constructor(
message: string,
public statusCode?: number,
public retryable: boolean = false
) {
super(message);
this.name = "DocumensoError";
}
}
export async function withErrorHandling<T>(
operation: string,
fn: () => Promise<T>
): Promise<T> {
try {
return await fn();
} catch (err: any) {
const status = err.statusCode ?? err.status;
switch (status) {
case 401:
throw new DocumensoError(`${operation}: Invalid API key`, 401, false);
case 403:
throw new DocumensoError(
`${operation}: Insufficient permissions — use team API key`,
403,
false
);
case 404:
throw new DocumensoError(`${operation}: Resource not found`, 404, false);
case 429:
throw new DocumensoError(`${operation}: Rate limited`, 429, true);
case 500:
case 502:
case 503:
throw new DocumensoError(
`${operation}: Documenso server error`,
status,
true
);
default:
throw new DocumensoError(
`${operation}: ${err.message ?? "Unknown error"}`,
status,
false
);
}
}
}
```
### Pattern 4: Retry with Exponential Backoff
```typescript
// src/documenso/retry.ts
import { DocumensoError } from "./errors";
interface RetryConfig {
maxRetries: number;
baseDelayMs: number;
maxDelayMs: number;
}
const DEFAULT_RETRY: RetryConfig = {
maxRetries: 3,
baseDelayMs: 1000,
maxDelayMs: 30000,
};
export async function withRetry<T>(
fn: () => Promise<T>,
config: Partial<RetryConfig> = {}
): Promise<T> {
const { maxRetries, baseDelayMs, maxDelayMs } = { ...DEFAULT_RETRY, ...config };
let lastError: Error | undefined;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (err) {
lastError = err as Error;
if (err instanceof DocumensoError && !err.retryable) throw err;
if (attempt === maxRetries) break;
const delay = Math.min(baseDelayMs * 2 ** attempt, maxDelayMs);
const jitter = delay * (0.5 + Math.random() * 0.5);
await new Promise((r) => setTimeout(r, jitter));
}
}
throw lastError;
}
```
### Pattern 5: Python Service Pattern
```python
# src/documenso/service.py
from documenso_sdk_python import Documenso
from dataclasses import dataclass
from typing import Optional
import os
@dataclass
class SignerInput:
email: str
name: str
field_type: str = "SIGNATURE"
page: int = 1
x: float = 50.0
y: float = 80.0
class DocumensoService:
def __init__(self, api_key: Optional[str] = None, base_url: Optional[str] = None):
self.client = Documenso(
api_key=api_key or os.environ["DOCUMENSO_API_KEY"],
**({"server_url": base_url} if base_url else {}),
)
def create_and_send(
self, title: str, pdf_path: str, signers: list[SignerInput]
) -> dict:
doc = self.client.documents.create_v0(title=title)
with open(pdf_path, "rb") as f:
self.client.documents.set_file_v0(doc.document_id, file=f.read())
recipient_ids = []
for signer in signers:
recip = self.client.documents_recipients.create_v0(
doc.document_id, email=signer.email, name=signer.name, role="SIGNER"
)
recipient_ids.append(recip.recipient_id)
self.client.documents_fields.create_v0(
doc.document_id,
recipient_id=recip.recipient_id,
type=signer.field_type,
page_number=signer.page,
page_x=signer.x,
page_y=signer.y,
)
self.client.documents.send_v0(doc.document_id)
return {"document_id": doc.document_id, "recipient_ids": recipient_ids}
```
### Pattern 6: Testing with Mocks
```typescript
// tests/mocks/documenso.ts
import { vi } from "vitest";
export function createMockClient() {
return {
documents: {
createV0: vi.fn().mockResolvedValue({ documentId: 1 }),
setFileV0: vi.fn().mockResolvedValue(undefined),
findV0: vi.fn().mockResolvedValue({ documents: [] }),
sendV0: vi.fn().mockResolvedValue(undefined),
deleteV0: vi.fn().mockResolvedValue(undefined),
},
documentsRecipients: {
createV0: vi.fn().mockResolvedValue({ recipientId: 100 }),
},
documentsFields: {
createV0: vi.fn().mockResolvedValue({ fieldId: 200 }),
},
};
}
```
## Error Handling
| Pattern Issue | Cause | Solution |
|--------------|-------|----------|
| Client not initialized | Missing env var | Check `DOCUMENSO_API_KEY` is set |
| Singleton stale after key rotation | Cached client | Call `resetClient()` |
| Retry loop on 401 | Non-retryable treated as retryable | Check `retryable` flag |
| Type mismatch on field type | Wrong enum string | Use union type from SDK |
## Resources
- [TypeScript SDK Source](https://github.com/documenso/sdk-typescript)
- [Python SDK Source](https://github.com/documenso/sdk-python)
- [SDK Documents API](https://github.com/documenso/sdk-typescript/blob/main/docs/sdks/documents/README.md)
- [Zod for Validation](https://zod.dev/)
## Next Steps
Apply patterns in `documenso-core-workflow-a` for document creation workflows.Related Skills
exa-sdk-patterns
Apply production-ready exa-js SDK patterns with type safety, singletons, and wrappers. Use when implementing Exa integrations, refactoring SDK usage, or establishing team coding standards for Exa. Trigger with phrases like "exa SDK patterns", "exa best practices", "exa code patterns", "idiomatic exa", "exa wrapper".
exa-reliability-patterns
Implement Exa reliability patterns: query fallback chains, circuit breakers, and graceful degradation. Use when building fault-tolerant Exa integrations, implementing fallback strategies, or adding resilience to production search services. Trigger with phrases like "exa reliability", "exa circuit breaker", "exa fallback", "exa resilience", "exa graceful degradation".
evernote-sdk-patterns
Advanced Evernote SDK patterns and best practices. Use when implementing complex note operations, batch processing, search queries, or optimizing SDK usage. Trigger with phrases like "evernote sdk patterns", "evernote best practices", "evernote advanced", "evernote batch operations".
elevenlabs-sdk-patterns
Apply production-ready ElevenLabs SDK patterns for TypeScript and Python. Use when implementing ElevenLabs integrations, refactoring SDK usage, or establishing team coding standards for audio AI applications. Trigger: "elevenlabs SDK patterns", "elevenlabs best practices", "elevenlabs code patterns", "idiomatic elevenlabs", "elevenlabs typescript".
documenso-webhooks-events
Implement Documenso webhook configuration and event handling. Use when setting up webhook endpoints, handling document events, or implementing real-time notifications for document signing. Trigger with phrases like "documenso webhook", "documenso events", "document completed webhook", "signing notification".
documenso-upgrade-migration
Manage 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".
documenso-security-basics
Implement security best practices for Documenso document signing integrations. Use when securing API keys, configuring webhooks securely, or implementing document security measures. Trigger with phrases like "documenso security", "secure documenso", "documenso API key security", "documenso webhook security".
documenso-reference-architecture
Implement Documenso reference architecture with best-practice project layout. Use when designing new Documenso integrations, reviewing project structure, or establishing architecture standards for document signing applications. Trigger with phrases like "documenso architecture", "documenso best practices", "documenso project structure", "how to organize documenso".
documenso-rate-limits
Implement Documenso rate limiting, backoff, and request throttling patterns. Use when handling rate limit errors, implementing retry logic, or optimizing API request throughput for Documenso. Trigger with phrases like "documenso rate limit", "documenso throttling", "documenso 429", "documenso retry", "documenso backoff".
documenso-prod-checklist
Execute Documenso production deployment checklist and rollback procedures. Use when deploying Documenso integrations to production, preparing for launch, or implementing go-live procedures. Trigger with phrases like "documenso production", "deploy documenso", "documenso go-live", "documenso launch checklist".
documenso-performance-tuning
Optimize Documenso integration performance with caching, batching, and efficient patterns. Use when improving response times, reducing API calls, or optimizing bulk document operations. Trigger with phrases like "documenso performance", "optimize documenso", "documenso caching", "documenso batch operations".
documenso-observability
Implement monitoring, logging, and tracing for Documenso integrations. Use when setting up observability, implementing metrics collection, or debugging production issues. Trigger with phrases like "documenso monitoring", "documenso metrics", "documenso logging", "documenso tracing", "documenso observability".