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:
2026-05-11 14:38:45 +02:00
parent ad312df8a4
commit d597e158fe
8 changed files with 365 additions and 58 deletions

View File

@@ -29,7 +29,7 @@ const API_FIELDS: SettingFieldDef[] = [
key: 'documenso_api_version_override',
label: 'API version',
description:
"Which Documenso REST API this port targets. v1 = Documenso 1.13.x stable. v2 = Documenso 2.x with the envelope model and richer per-field metadata. Test the connection after switching. See the v2 benefits card above for what changes when you flip this — and note that template-based EOI generation still uses the v1 formValues shape regardless of this setting (v2 template/use migration is on the roadmap).",
'Which Documenso REST API this port targets. v1 = Documenso 1.13.x stable. v2 = Documenso 2.x with the envelope model and richer per-field metadata. Test the connection after switching. See the v2 benefits card above for what changes when you flip this — and note that template-based EOI generation still uses the v1 formValues shape regardless of this setting (v2 template/use migration is on the roadmap).',
type: 'select',
options: [
{ value: 'v1', label: 'v1 — Documenso 1.13.x (default, stable)' },
@@ -144,6 +144,30 @@ const EMBED_FIELDS: SettingFieldDef[] = [
},
];
const V2_FEATURE_FIELDS: SettingFieldDef[] = [
{
key: 'documenso_signing_order',
label: 'Signing order',
description:
'PARALLEL = recipients can sign in any order (faster, current default). SEQUENTIAL = Documenso refuses to email recipient N+1 until recipient N has signed, enforcing client → developer → approver order on EOIs. Only applies when API version above is v2 — v1 instances ignore this and always behave as PARALLEL.',
type: 'select',
options: [
{ value: '', label: 'PARALLEL (default)' },
{ value: 'SEQUENTIAL', label: 'SEQUENTIAL — enforce signing order (v2 only)' },
],
defaultValue: '',
},
{
key: 'documenso_redirect_url',
label: 'Post-signing redirect URL',
description:
"URL Documenso redirects the signer to after they complete signing. Typically the marketing site's success page so signers land on a branded thank-you rather than Documenso's own page. Leave blank to use Documenso's default. v1 and v2 both honour this. Example: https://portnimara.com/sign/success",
type: 'string',
placeholder: 'https://portnimara.com/sign/success',
defaultValue: '',
},
];
export default function DocumensoSettingsPage() {
return (
<div className="space-y-6">
@@ -162,10 +186,10 @@ export default function DocumensoSettingsPage() {
<CardContent className="space-y-4 text-sm">
<p className="text-muted-foreground">
The CRM supports both Documenso 1.13.x (v1) and 2.x (v2). v1 is the default for
backwards compatibility. v2 is recommended for new ports and unlocks the features
below. Switching versions does <strong>not</strong> require any code changes
version-aware client methods pick the right endpoint per port. Switch, save, then run
the test-connection button to confirm the chosen instance is actually on the matching
backwards compatibility. v2 is recommended for new ports and unlocks the features below.
Switching versions does <strong>not</strong> require any code changes version-aware
client methods pick the right endpoint per port. Switch, save, then run the
test-connection button to confirm the chosen instance is actually on the matching
Documenso version.
</p>
@@ -175,7 +199,10 @@ export default function DocumensoSettingsPage() {
</p>
<ul className="space-y-1.5">
<li className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600" aria-hidden="true" />
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Bulk field placement.</strong> One API call per envelope vs. v1&apos;s
per-field POST loop. Faster contract generation, fewer transient retries on
@@ -183,23 +210,32 @@ export default function DocumensoSettingsPage() {
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600" aria-hidden="true" />
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Percent-based field coordinates.</strong> No page-dimension lookup
needed coordinates are portable across page sizes. v1 requires us to assume A4
for auto-placed fields.
<strong>Percent-based field coordinates.</strong> No page-dimension lookup needed
coordinates are portable across page sizes. v1 requires us to assume A4 for
auto-placed fields.
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600" aria-hidden="true" />
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Richer field metadata.</strong> TEXT labels &amp; required flags, NUMBER
min/max + format, CHECKBOX/DROPDOWN/RADIO option lists with defaults all
ignored by v1, surfaced by v2 in the signing UI.
min/max + format, CHECKBOX/DROPDOWN/RADIO option lists with defaults all ignored
by v1, surfaced by v2 in the signing UI.
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600" aria-hidden="true" />
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>v2-flavoured webhook events.</strong> <code>RECIPIENT_VIEWED</code>,{' '}
<code>RECIPIENT_SIGNED</code>, <code>DOCUMENT_RECIPIENT_COMPLETED</code>,{' '}
@@ -208,11 +244,54 @@ export default function DocumensoSettingsPage() {
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2 className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600" aria-hidden="true" />
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Envelope/embed endpoints.</strong> <code>GET</code> and{' '}
<code>DELETE</code> go through <code>/api/v2/envelope/...</code> when v2 is
selected. Future embedded-signing iframe work will plug in here.
<strong>Envelope CRUD endpoints.</strong> <code>GET</code>, <code>DELETE</code>,
<code>POST /envelope/create</code> (multipart), <code>POST /envelope/distribute</code>,{' '}
<code>POST /envelope/redistribute</code>, <code>GET /envelope/{'{id}'}/download</code>{' '}
all routed through <code>/api/v2/envelope/...</code> when v2 is selected. The
template-generate path is intentionally still v1 (relies on Documenso 2.x&apos;s
backward-compat window see the deferred-roadmap below).
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>One-call send.</strong> v2&apos;s <code>/envelope/distribute</code> returns
per-recipient <code>signingUrl</code> in the same response v1 requires a
separate GET to fetch them. Faster send flow on the rep side.
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Sequential signing enforcement.</strong> Pick SEQUENTIAL in the &quot;v2
signing behaviour&quot; card below and Documenso 2.x refuses to email recipient
N+1 until recipient N has signed. Eliminates the &quot;approver signed before the
developer did&quot; race on EOIs.
</span>
</li>
<li className="flex items-start gap-2">
<CheckCircle2
className="mt-0.5 h-4 w-4 flex-shrink-0 text-emerald-600"
aria-hidden="true"
/>
<span>
<strong>Post-signing redirect URL.</strong> Set in the &quot;v2 signing
behaviour&quot; card; Documenso redirects the signer to that URL after they
complete signing. Use to land clients on the marketing site&apos;s success page
or back in the portal instead of Documenso&apos;s default thank-you page. (v1
honours this too listed here because the admin setting was added with the v2
work.)
</span>
</li>
</ul>
@@ -220,35 +299,35 @@ export default function DocumensoSettingsPage() {
<div className="rounded-md border border-amber-200 bg-amber-50/60 p-3 dark:border-amber-900/40 dark:bg-amber-950/30">
<p className="mb-2 text-xs font-semibold uppercase tracking-wider text-amber-700 dark:text-amber-400">
v2 capabilities on the roadmap (not yet wired)
v2 capabilities deferred (would need new code paths)
</p>
<ul className="space-y-1.5 text-muted-foreground">
<li>
<strong>Sequential signing</strong> (<code>signingOrder: SEQUENTIAL</code>) would
force client developer approver order on EOIs instead of all-at-once.
<strong>
Single-shot <code>/template/use</code>
</strong>{' '}
with v2 <code>prefillFields</code> by ID current EOI flow uses{' '}
<code>/api/v1/templates/{'{id}'}/generate-document</code> with{' '}
<code>formValues</code> keyed by name. v2 instances accept both during their
backward-compat window; full migration requires per-template field-ID capture in
admin settings.
</li>
<li>
<strong>Post-signing redirect URL</strong> (<code>redirectUrl</code>) would land
signed clients back on the portal rather than Documenso&apos;s page.
<strong>
Update envelope metadata after creation (<code>/envelope/update</code>)
</strong>{' '}
change title / subject / redirectUrl on a doc already in DRAFT/PENDING without
re-generating.
</li>
<li>
<strong>Single-shot <code>/template/use</code></strong> (v2 prefillFields by ID
replacing v1 formValues by name) currently the EOI flow still uses the v1
template path even when API version is v2. Needs per-template field-ID mapping in
the template config before we can switch.
</li>
<li>
<strong>Update envelope metadata</strong> (<code>/envelope/update</code>) change
title / subject / redirectUrl after creation without re-generating.
</li>
<li>
<strong>Recipient roles beyond SIGNER</strong> (APPROVER / CC / VIEWER) would let
sales managers receive copies without a signature slot.
<strong>Non-SIGNER recipient roles (CC / VIEWER)</strong> APPROVER role is
already used by the EOI template; CC + VIEWER not yet exposed in the recipient
builder. Useful for sales managers who want a copy without a signature slot.
</li>
</ul>
<p className="mt-2 text-xs text-muted-foreground">
These items have no admin setting yet because they need code changes first. They
live here so you know what&apos;s in the pipeline.
Sequential signing and post-signing redirect URL <strong>are now wired</strong>
see the new &quot;v2 signing behaviour&quot; card below to configure them.
</p>
</div>
</CardContent>
@@ -261,6 +340,12 @@ export default function DocumensoSettingsPage() {
extra={<DocumensoTestButton />}
/>
<SettingsFormCard
title="v2 signing behaviour"
description="Cross-cutting settings that apply to EOIs + uploaded contracts/reservations. Sequential signing is v2-only (v1 instances ignore it). Redirect URL is honoured by both v1 and v2 instances."
fields={V2_FEATURE_FIELDS}
/>
<SettingsFormCard
title="Signers (developer + approver)"
description="Identity of the static signers in your Documenso templates. The client is always pulled from the interest's linked client record; these values fill the developer (signing order 2) and approver (signing order 3) slots."