feat(documenso): full v2 endpoint coverage + sequential signing + redirectUrl
Wire up the remaining version-aware paths so a port pointed at Documenso 2.x
takes the v2 endpoint on every CRUD operation, with two new v2-only settings
exposed in admin UI.
documenso-client.ts:
- createDocument: v2 multipart /envelope/create + getDocument follow-up to
return the full doc shape (v1 path unchanged)
- sendDocument: v2 /envelope/distribute (returns per-recipient signingUrl in
the same response — eliminates the v1 separate-GET round-trip)
- sendReminder: v2 /envelope/redistribute with recipientIds filter
- downloadSignedPdf: v2 /envelope/{id}/download
- CreateDocumentMeta type: { subject, message, redirectUrl, signingOrder }
threaded through v1 + v2 paths (v1 ignores signingOrder)
port-config.ts:
- New settings: documenso_signing_order (PARALLEL/SEQUENTIAL, v2-only),
documenso_redirect_url (both versions honour)
- PortDocumensoConfig gains signingOrder + redirectUrl
documenso-payload.ts:
- DocumensoTemplatePayload.meta gains signingOrder
- buildDocumensoPayload reads from options.signingOrder, omits when null
document-templates.ts (EOI template flow):
- Pass docCfg.signingOrder + docCfg.redirectUrl into buildDocumensoPayload
documents.service.ts (sendForSigning uploaded-doc flow):
- Pass portId to documensoCreate + documensoSend (was missing)
- Thread signingOrder + redirectUrl via the new meta param
Admin Documenso settings page:
- v2 benefits card updated: now lists envelope CRUD, one-call send,
sequential enforcement, post-sign redirect as wired (was roadmap)
- Roadmap callout pruned to the three remaining deferred items:
template/use migration, /envelope/update, non-SIGNER recipient roles
- New "v2 signing behaviour" SettingsFormCard with the two new settings
Template flow stays on /api/v1/templates/{id}/generate-document by design —
Documenso 2.x accepts v1 endpoints via backward compat; full migration to
v2 /template/use requires per-template field-ID capture (admin schema work,
deferred).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,16 @@ export const SETTING_KEYS = {
|
||||
// uses templates rather than per-deal uploads. Optional.
|
||||
documensoContractTemplateId: 'documenso_contract_template_id',
|
||||
documensoReservationTemplateId: 'documenso_reservation_template_id',
|
||||
// v2-only: PARALLEL (default) or SEQUENTIAL signing-order enforcement on
|
||||
// multi-recipient envelopes. When SEQUENTIAL is set + apiVersion=v2,
|
||||
// Documenso refuses to email recipient N+1 until recipient N has signed.
|
||||
// Ignored entirely on v1 instances.
|
||||
documensoSigningOrder: 'documenso_signing_order',
|
||||
// v2-only override of the post-signing redirect URL set on documentMeta.
|
||||
// Falls back to the embedded signing host (or APP_URL) when unset. Use
|
||||
// this to land signed clients on /portal/eoi-complete (or wherever
|
||||
// makes sense for the workflow).
|
||||
documensoRedirectUrl: 'documenso_redirect_url',
|
||||
|
||||
// Branding
|
||||
brandingLogoUrl: 'branding_logo_url',
|
||||
@@ -222,6 +232,19 @@ export interface PortDocumensoConfig {
|
||||
* user's email for in-CRM signing-status updates. */
|
||||
developerUserId: string | null;
|
||||
approverUserId: string | null;
|
||||
/**
|
||||
* v2-only: PARALLEL (default) or SEQUENTIAL signing-order enforcement.
|
||||
* `null` keeps the upstream default (PARALLEL); a non-null value gets
|
||||
* passed verbatim. v1 instances ignore this — see admin Documenso page.
|
||||
*/
|
||||
signingOrder: 'PARALLEL' | 'SEQUENTIAL' | null;
|
||||
/**
|
||||
* v2-only: post-signing redirect URL set on documentMeta. When null,
|
||||
* the upstream Documenso default applies (Documenso's own thank-you
|
||||
* page). Typically set to `{embeddedSigningHost}/sign/success` so
|
||||
* signers land back on the branded marketing site.
|
||||
*/
|
||||
redirectUrl: string | null;
|
||||
}
|
||||
|
||||
function toIntOrNull(raw: unknown): number | null {
|
||||
@@ -255,6 +278,8 @@ export async function getPortDocumensoConfig(portId: string): Promise<PortDocume
|
||||
approverLabel,
|
||||
developerUserId,
|
||||
approverUserId,
|
||||
signingOrder,
|
||||
redirectUrlOverride,
|
||||
] = await Promise.all([
|
||||
readSetting<string>(SETTING_KEYS.documensoApiUrlOverride, portId),
|
||||
readSetting<string>(SETTING_KEYS.documensoApiKeyOverride, portId),
|
||||
@@ -276,6 +301,8 @@ export async function getPortDocumensoConfig(portId: string): Promise<PortDocume
|
||||
readSetting<string>(SETTING_KEYS.documensoApproverLabel, portId),
|
||||
readSetting<string>(SETTING_KEYS.documensoDeveloperUserId, portId),
|
||||
readSetting<string>(SETTING_KEYS.documensoApproverUserId, portId),
|
||||
readSetting<'PARALLEL' | 'SEQUENTIAL'>(SETTING_KEYS.documensoSigningOrder, portId),
|
||||
readSetting<string>(SETTING_KEYS.documensoRedirectUrl, portId),
|
||||
]);
|
||||
|
||||
return {
|
||||
@@ -299,6 +326,8 @@ export async function getPortDocumensoConfig(portId: string): Promise<PortDocume
|
||||
approverLabel: approverLabel ?? 'Approver',
|
||||
developerUserId: developerUserId ?? null,
|
||||
approverUserId: approverUserId ?? null,
|
||||
signingOrder: signingOrder ?? null,
|
||||
redirectUrl: redirectUrlOverride ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user