| name | documenso-multi-env-setup |
| description | Configure Documenso across multiple environments (dev, staging, production).
Use when setting up environment-specific configurations, managing API keys,
or implementing environment promotion workflows.
Trigger with phrases like "documenso environments", "documenso staging",
"documenso dev setup", "multi-environment documenso".
|
| allowed-tools | Read, Write, Edit |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
Documenso Multi-Environment Setup
Overview
Configure and manage Documenso integrations across development, staging, and production environments with proper isolation and promotion workflows.
Prerequisites
- Documenso accounts for each environment (or self-hosted instances)
- Environment management infrastructure
- Secret management solution (Vault, AWS Secrets Manager, etc.)
Environment Architecture
┌─────────────────────────────────────────────────────────┐
│ Development │
│ API: stg-app.documenso.com (staging) │
│ Key: DOCUMENSO_API_KEY_DEV │
│ Purpose: Local development, testing │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Staging │
│ API: stg-app.documenso.com │
│ Key: DOCUMENSO_API_KEY_STAGING │
│ Purpose: Integration testing, QA │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Production │
│ API: app.documenso.com │
│ Key: DOCUMENSO_API_KEY_PRODUCTION │
│ Purpose: Live customer traffic │
└─────────────────────────────────────────────────────────┘
Configuration Files
Environment-Specific Configs
{
"baseUrl": "https://stg-app.documenso.com/api/v2/",
"timeout": 30000,
"debug": true,
"mockEnabled": true,
"testRecipients": ["dev@yourcompany.com"],
"cacheOptions": {
"enabled": false,
"ttl": 60
}
}
{
"baseUrl": "https://stg-app.documenso.com/api/v2/",
"timeout": 30000,
"debug": true,
"mockEnabled": false,
"testRecipients": ["staging-test@yourcompany.com"],
"cacheOptions": {
"enabled": true,
"ttl": 300
}
}
{
"baseUrl": "https://app.documenso.com/api/v2/",
"timeout": 30000,
"debug": false,
"mockEnabled": false,
"testRecipients": [],
"cacheOptions": {
"enabled": true,
"ttl": 600
}
}
Configuration Loader
import { z } from "zod";
const EnvironmentSchema = z.enum(["development", "staging", "production"]);
type Environment = z.infer<typeof EnvironmentSchema>;
const ConfigSchema = z.object({
baseUrl: z.string().url(),
timeout: z.number().default(30000),
debug: z.boolean().default(false),
mockEnabled: z.boolean().default(false),
testRecipients: z.array(z.string().email()).default([]),
cacheOptions: z.object({
enabled: z.boolean(),
ttl: z.number(),
}),
});
export type DocumensoConfig = z.infer<typeof ConfigSchema>;
export (): {
env = process.. ?? ;
.(env);
}
(): & { : } {
env = ();
fileConfig = ();
apiKeyVar = ;
apiKey = process.[apiKeyVar] ?? process..;
(!apiKey) {
();
}
config = {
....(fileConfig),
apiKey,
: process.. ?? fileConfig.,
};
config;
}
Environment Variables
.env.development
NODE_ENV=development
DOCUMENSO_API_KEY_DEVELOPMENT=dcs_dev_xxx
DOCUMENSO_API_KEY=${DOCUMENSO_API_KEY_DEVELOPMENT}
DOCUMENSO_BASE_URL=https://stg-app.documenso.com/api/v2/
DOCUMENSO_WEBHOOK_SECRET=dev-webhook-secret
.env.staging
NODE_ENV=staging
DOCUMENSO_API_KEY_STAGING=dcs_staging_xxx
DOCUMENSO_WEBHOOK_SECRET=staging-webhook-secret
.env.production
NODE_ENV=production
DOCUMENSO_API_KEY_PRODUCTION=dcs_prod_xxx
DOCUMENSO_WEBHOOK_SECRET=prod-webhook-secret
Client Factory
import { Documenso } from "@documenso/sdk-typescript";
import { loadConfig, getEnvironment } from "../config/documenso";
interface ClientOptions {
forceEnvironment?: "development" | "staging" | "production";
mockMode?: boolean;
}
const clients = new Map<string, Documenso>();
export function getDocumensoClient(options?: ClientOptions): Documenso {
const env = options?.forceEnvironment ?? getEnvironment();
const cacheKey = `${env}-${options?.mockMode ?? false}`;
if (clients.has(cacheKey)) {
return clients.get(cacheKey)!;
}
const config = loadConfig();
if (options?.mockMode && config.mockEnabled) {
console.log(`[Documenso] Using mock client for `);
();
}
client = ({
: config.,
: config.,
: config.,
: config. ? : ,
});
clients.(cacheKey, client);
.();
.();
client;
}
(): {
clients.();
}
Mock Client for Development
import { Documenso } from "@documenso/sdk-typescript";
let mockDocumentCounter = 0;
export function createMockClient(): Documenso {
const mockClient = {
documents: {
createV0: async (input: any) => {
mockDocumentCounter++;
console.log(`[MOCK] Creating document: ${input.title}`);
return {
documentId: `mock_doc_${mockDocumentCounter}`,
title: input.title,
status: "DRAFT",
};
},
getV0: async ({ documentId }: any) => {
console.log(`[MOCK] Getting document: ${documentId}`);
return {
id: documentId,
title: "Mock Document",
status: "PENDING",
recipients: [],
};
},
findV0: async () => {
console.();
{ : [], : };
},
: ({ documentId }: ) => {
.();
{ : };
},
},
: {
: ({ templateId }: ) => {
.();
{
: templateId,
: ,
: [],
};
},
},
};
mockClient ;
}
Environment Promotion
import { getDocumensoClient } from "../src/documenso/factory";
interface TemplateMapping {
stagingId: string;
productionId?: string;
name: string;
}
const TEMPLATE_MAPPINGS: TemplateMapping[] = [
{ stagingId: "tmpl_stg_nda", name: "NDA Template" },
{ stagingId: "tmpl_stg_contract", name: "Contract Template" },
];
async function promoteTemplates() {
const stagingClient = getDocumensoClient({ forceEnvironment: "staging" });
const prodClient = getDocumensoClient({ forceEnvironment: "production" });
console.log("Promoting templates from staging to production...\n");
for (const mapping of TEMPLATE_MAPPINGS) {
try {
const stagingTemplate = await stagingClient..({
: mapping.,
});
.();
.();
.();
.();
.();
.();
} (: ) {
.();
}
}
}
().(.);
Webhook Configuration Per Environment
import { getEnvironment } from "../config/documenso";
interface WebhookConfig {
url: string;
secret: string;
events: string[];
}
export function getWebhookConfig(): WebhookConfig {
const env = getEnvironment();
const configs: Record<string, WebhookConfig> = {
development: {
url: "https://dev.yourapp.com/webhooks/documenso",
secret: process.env.DOCUMENSO_WEBHOOK_SECRET_DEV ?? "",
events: ["document.created", "document.completed"],
},
staging: {
url: "https://staging.yourapp.com/webhooks/documenso",
secret: process.env.DOCUMENSO_WEBHOOK_SECRET_STAGING ?? "",
events: [
"document.created",
"document.sent",
"document.signed",
"document.completed",
],
},
production: {
url: "https://app.yourapp.com/webhooks/documenso",
: process.. ?? ,
: [
,
,
,
,
,
,
,
],
},
};
configs[env];
}
Testing Across Environments
import { describe, it, expect, beforeAll } from "vitest";
import { getDocumensoClient, resetClients } from "../../src/documenso/factory";
describe("Multi-Environment Configuration", () => {
beforeAll(() => {
resetClients();
});
it("connects to staging environment", async () => {
const client = getDocumensoClient({ forceEnvironment: "staging" });
const result = await client.documents.findV0({ perPage: 1 });
expect(result).toBeDefined();
});
it("uses mock client in development with mockMode", async () => {
const client = getDocumensoClient({
forceEnvironment: "development",
mockMode: true,
});
const doc = await client.documents.createV0({ title: "Test" });
expect(doc.documentId).toMatch(/^mock_doc_/);
});
(, () => {
config = ();
(config.).();
(config.).();
});
});
Environment Checklist
Development
Staging
Production
Output
- Environment-specific configurations
- Isolated API keys per environment
- Promotion workflow documented
- Mock client for development
Error Handling
| Issue | Cause | Solution |
|---|
| Wrong environment | Missing NODE_ENV | Set explicitly |
| Key mismatch | Using wrong key | Check env var names |
| Config not loading | File path wrong | Verify config files |
| Mock not working | mockEnabled: false | Enable in dev config |
Resources
Next Steps
For monitoring setup, see documenso-observability.