DocuSign Signing
When DocuSign is connected (see Integrations → DocuSign), contracts can be sent as native DocuSign envelopes. Recipients sign on DocuSign's own UI, status flows back into Kinderpedia in real-time, and the completed PDF lands in your S3 storage automatically.
Sending a contract via DocuSign
On a contract detail page (/contracts/{id}), the Send action gives you two choices:
| Channel | What happens |
|---|---|
| Email all participants | Generates per-participant share-token URLs and emails them. Recipient clicks → signs on Kinderpedia's own signing surface. |
| DocuSign envelope | Sends a real DocuSign envelope. Each participant receives a DocuSign email + signs on DocuSign. |
Both paths end with a signed PDF; DocuSign is preferred when you need legal-grade audit trails (Certificate of Completion, timestamping, multi-factor signer auth).
Per-template signing config
Each contract template (under Templates → Contracts) can be configured with:
- Default signing channel: DocuSign / Email / Either
- Signer order: parallel (everyone signs at once) vs sequential (Mum signs first, then Dad, then admin)
- Reminder cadence: 1 day / 3 days / 7 days
- DocuSign tabs preset: which fields auto-populate (date signed, full name, initial, etc.)
See Template signing configuration for the full setup.
What gets sent
When you click Send via DocuSign:
- Backend reads the contract's participants (linked from the lead's
family_members). - For each participant, builds a DocuSign signer block with:
recipientId— sequential int (1, 2, 3, …)email— fromcontract_participants.participant_emailname— from the linked parent's full nameroutingOrder— 1 for parallel, or matches template's sequencetabs— date/sign/initial fields placed on the PDF
- POSTs
/v2.1/accounts/{accountId}/envelopeswith the contract PDF + signers + email subject/body. - DocuSign creates the envelope (
envelopeId) and emails the first signer (or all, if parallel). - We stamp
contracts.docusign_envelope_id+ initial statussent+docusign_recipientsJSON snapshot of the signer list.
Signer status sync
There are two paths to keep status fresh:
DocuSign Connect (webhook — recommended)
If DocuSign Connect is configured (one-time at the DocuSign Admin level, per Kinderpedia instance), each signing event fires a push to /api/integrations/docusign/webhook within seconds. We:
- Validate the HMAC signature.
- Decode the event payload (XML or JSON, depending on Connect config).
- Update the contract row + each participant row.
- If the envelope is now
completed, fetch the signed PDF + Certificate of Completion + store on S3.
Real-time updates, no polling required.
Manual refresh
Without Connect, you click Refresh status on the contract page. We call GET /envelopes/{id} + GET /envelopes/{id}/recipients to pull current state and reconcile. Latency depends on when you click — useful for spot-checks but tedious for high-volume schools.
The Signers card
On the contract detail page, a single Signers card (formerly two separate cards "DocuSign status" + "Participants") shows:
Header strip (only when DocuSign envelope exists)
DocuSign [Sent] · Envelope cb2f8e9a-… · Sent May 12, 2026, 14:32 · Updated May 12, 2026, 14:45
[Refresh status] [View in DocuSign →]The status pill turns green when all participants sign (Completed), amber when declined / voided.
docusign_last_error (if any) renders as a red banner above the participant rows.
Per-participant rows
Each participant — Mum, Dad, school admin — gets one row:
- Avatar with initials
- Name + role badge (Father / Mother / CEO / etc.)
- Email + ✏️ pencil button (to correct email)
- Status badge per participant:
Pending/Delivered/Viewed/Signed/Declined - Timestamp for the most recent transition (
signed_at,declined_at,viewed_at) - Decline reason if declined
- ✈️ paper-plane button to resend the signing email
Pencil edit (email correction)
If you discover a parent's email is wrong while the envelope is in flight:
- Click the pencil next to their row.
- Edit the email in the modal.
- DocuSign will resend the signing email to the new address. (Warning copy in the modal.)
- Save.
We call PUT /envelopes/{id}/recipients?resend_envelope=true to:
- Update the recipient's email server-side at DocuSign.
- Trigger DocuSign to email the corrected address.
The local contract_participants.participant_email + contracts.docusign_recipients JSON are also updated for consistency.
The pencil is hidden when:
- Envelope is in a terminal state (
completed,declined,voided) - This specific participant has already signed / declined
(DocuSign won't allow correction of already-signed recipients.)
Paper-plane resend
Click the ✈️ next to a pending recipient → DocuSign sends a fresh signing email. Useful when the original landed in spam or the parent says "I didn't get it."
For contracts NOT sent via DocuSign (the share-token email path), the same button regenerates and re-emails the share-token URL instead — the controller picks the right behaviour based on whether docusign_envelope_id is set.
Voiding an envelope
The header has Void envelope (admin-only, contract-level permission). Voiding:
- Prompts for a reason.
- Calls
PUT /envelopes/{id}withstatus = voided+ reason. - DocuSign kills the envelope — no further signing possible, no auto-notification to recipients.
- Local contract status flips to
voided.
After voiding, you can't "undo." To collect signatures, create a new contract envelope.
Completed envelopes
When the last participant signs:
- DocuSign sends
envelope-completedevent via Connect (or you click Refresh). - We fetch the signed PDF via
GET /envelopes/{id}/documents/combined. - Fetch the Certificate of Completion via
/documents/certificate. - Upload both to your school's private contracts storage.
- Contract status →
signed. - Per-template auto-actions kick in:
- If linked to a Google Drive integration (sender's), push the signed PDF.
- If a workflow trigger watches
contract.signed, fire it.
Audit log entries
DocuSign-related events fire audit_logs entries:
contract_envelope_created— envelope id, recipient list snapshotcontract_envelope_status_changed— old → new, per-participant snapshotparticipant_email_corrected_docusign— participant id, old → new emaildocusign_reminder_sent— participant idcontract_envelope_voided— reason, who voidedcontract_envelope_completed— final state
The activity-log feed on the contract detail page surfaces these in human-readable form (with a "View more" toggle when >10 entries).
Common errors
| Symptom | Likely cause |
|---|---|
| Send returns 401 | Refresh token revoked. Re-connect DocuSign integration. |
| Status pill stuck at "Sent" forever | DocuSign Connect not configured. Manual refresh required. |
| Pencil edit returns "ENVELOPE_CANNOT_CORRECT" | Recipient already signed/declined. Edit disabled. |
| Pencil shows but save fails 422 | Race — recipient signed between page load and save. Refresh + retry. |
| Refresh shows no change but DocuSign UI shows signed | Connect endpoint URL changed without restarting Kinderpedia. Restart. |
Sandbox vs production
Sandbox uses account-d.docusign.com; production uses account.docusign.com. Your Kinderpedia admin picks which environment your instance targets. Sandbox signers don't exist in production — for end-to-end testing, both ends must be in sandbox.