Implement Documenso reference architecture with best-practice project layout. Use when designing new Documenso integrations, reviewing project structure, or establishing architecture standards for...
Route a synthetic development document through a scoped service identity, role-limited signer, validated webhook, and redacted audit metric. Promote the same versioned workflow through staging before a production canary; preserve a disabled/rollback path and do not include document URLs or signer identity in diagrams or logs.
Production-ready architecture for Documenso document signing integrations. Covers project layout, layered service architecture, webhook processing, and data flow.
documenso-sdk-patterns)my-signing-app/
βββ src/
β βββ documenso/
β β βββ client.ts # Singleton SDK client
β β βββ errors.ts # Custom error classes
β β βββ retry.ts # Retry/backoff logic
β β βββ types.ts # Shared types
β βββ services/
β β βββ document-service.ts # Document CRUD operations
β β βββ template-service.ts # Template-based workflows
β β βββ signing-service.ts # Orchestrates signing flows
β βββ webhooks/
β β βββ handler.ts # Express webhook router
β β βββ verify.ts # Secret verification
β β βββ processors/
β β βββ document-completed.ts
β β βββ document-signed.ts
β β βββ document-rejected.ts
β βββ api/
β β βββ health.ts # Health check endpoint
β β βββ routes.ts # API routes
β βββ config/
β βββ index.ts # Environment configuration
βββ scripts/
β βββ verify-connection.ts # Quick health check
β βββ create-test-doc.ts # Test document generator
β βββ cleanup-test-docs.ts # Test data cleanup
βββ tests/
β βββ unit/
β β βββ document-service.test.ts
β βββ integration/
β β βββ document-lifecycle.test.ts
β βββ mocks/
β βββ documenso.ts # Mock client factory
βββ .env.development
βββ .env.production
βββ docker-compose.yml # Self-hosted Documenso (dev)
βββ package.json
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API / Controllers β
β Routes, request validation, response formatting β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Service Layer β
β Business logic, orchestration, authorization β
β (document-service, template-service, signing-service) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Documenso Client Layer β
β SDK wrapper, retry, error handling, caching β
β (client.ts, retry.ts, errors.ts) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β External Services β
β Documenso API, S3/GCS storage, email, database β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Rules:
@documenso/sdk-typescript directly -- use the client wrapperUser Request
β
βΌ
ββββββββββββ POST /api/sign
β API ββββββββββββββββββββββββββββββββ
β Router β β
ββββββββββββ βΌ
ββββββββββββββββ
β Signing β
β Service β
ββββββββ¬ββββββββ
β
βββββββββββββββββββββββΌββββββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββ
β Template β β Document β β Your β
β Service β β Service β β DB β
ββββββ¬ββββββ ββββββ¬ββββββ ββββββββββββ
β β
ββββββββββ¬ββββββββββββ
βΌ
ββββββββββββββββ
β Documenso β
β Client ββββ Documenso API
β (singleton) β
ββββββββββββββββ
Webhook Flow:
Documenso API ββPOSTβββ /webhooks/documenso
β
ββββββΌβββββ
β Verify ββββ Check X-Documenso-Secret
β Secret β
ββββββ¬βββββ
β
ββββββΌβββββ
β Router ββββ Route by event type
ββββββ¬βββββ
β
ββββββββββββββββΌβββββββββββββββ
βΌ βΌ βΌ
completed.ts signed.ts rejected.ts
(archive PDF) (update DB) (alert sender)
#!/bin/bash
set -euo pipefail
mkdir -p src/{documenso,services,webhooks/processors,api,config}
mkdir -p scripts tests/{unit,integration,mocks}
# Create .env.example
cat > .env.example << 'EOF'
DOCUMENSO_API_KEY=
DOCUMENSO_BASE_URL=https://app.documenso.com/api/v2
DOCUMENSO_WEBHOOK_SECRET=
LOG_LEVEL=info
NODE_ENV=development
EOF
echo "Project scaffolded. Copy .env.example to .env and fill in values."
| Decision | Rationale |
|---|---|
| Singleton client | Avoids re-initialization overhead per request |
| Service layer | Separates business logic from API details |
| One processor per webhook event | Isolates side effects, easy to test |
| Mock client for tests | Fast unit tests without API calls |
| Template-first approach | Fewer API calls, consistent field placement |
| Issue | Cause | Solution |
|---|---|---|
| Circular dependencies | Wrong layering | Services import client, never the reverse |
| Config not loading | Wrong env file | Verify NODE_ENV matches config loader |
| Webhook processor crash | Unhandled error in processor | Wrap each processor in try/catch |
| Test isolation | Shared client state | Call resetClient() in beforeEach |
For multi-environment setup, see documenso-multi-env-setup.