Signing Flow
KarmaFlow ships with a fully integrated, self-hosted e-signature workflow. There is no third-party signing vendor involved — documents are signed inside the KarmaFlow signing portal, signatures are stamped onto the PDF by the platform, and a tamper-evident audit trail is embedded directly into the final document.
Status State Machine
Every document moves through a defined sequence of statuses:
drafting → draft → pending_review → approved → out_for_signature →
partially_signed → signed
↘ declined
↘ voided
↘ expired
- drafting — Document was created; AI generation has been requested or is in progress
- draft — AI has produced content; you're reviewing or editing
- pending_review — Optional intermediate state for multi-step approval
- approved — Author approved; ready to send to signers
- out_for_signature — Sent to one or more signers
- partially_signed — At least one but not all signers have completed
- signed — All signers completed; final PDF stamped and delivered
- declined — A signer rejected the document; flow halts
- voided — Author cancelled the document before all signatures were collected
- expired — A signing link reached its expiration before being used
Signer Configuration
Each signer record carries:
- Role (e.g., "Disclosing Party", "Client") — comes from the default signers configured on the document agent
- Name and email — required before sending
- Phone — optional; needed only if SMS OTP attribution is enabled
- Order — 1-indexed position in sequential signing
- Signature type —
signature (full signature) or initial
- Require OTP — optional flag for SMS-OTP attribution (schema-ready; SMS delivery wiring is a follow-up enhancement)
Sequential vs Parallel Routing
When you click Send for signature, the signing mode set on the document determines how invites are dispatched:
- Parallel — Every signer receives an invitation email immediately. They can sign in any order. The document moves to
signed when the last signer completes.
- Sequential — Only signer order #1 gets the initial email. When signer #1 finishes, signer #2 is automatically invited. This continues through the signer list. Useful for offer letters (hiring manager signs first, then the candidate countersigns) or any flow with a defined chain of authority.
You can choose sequential or parallel per document; or lock the signing mode at the agent level if every document of that type should use the same routing.
What the Signer Experiences
Each signer receives an email with a unique, signed URL. The URL is shaped like:
/sign/{tenantId}/{token}
The token is generated as 32 bytes of cryptographically random data, then hashed before storage — KarmaFlow never stores raw signing tokens. The plaintext token only exists in the recipient's email. Each token is single-use per signer and expires after 30 days by default.
When the signer clicks their link, they land on a clean, brandable signing portal that requires no account:
- Document preview — The full document, rendered in HTML
- Consent gate — A required checkbox: "I consent to do business electronically and agree that my electronic signature has the same legal effect as a handwritten signature. I understand I am entering into a legally binding agreement." This is captured per-signer with timestamp, IP address, user agent, and browser language — the ESIGN Act consent record
- Identity / attribution — The signer types their full legal name and/or draws their signature on the canvas
- Submit — Clicking Sign & Submit constitutes the affirmative "intent to sign" act under ESIGN/UETA
- Decline — Alternative path; the document moves to
declined and the flow halts
Final Stamping
When the last signer completes:
- The system fetches the latest unsigned PDF from cloud storage
- pdf-lib stamps each resolved signing field at its pixel coordinates:
signature — embeds the drawn signature PNG (or falls back to typed name if no canvas drawing)
initial — stamps signer's initials
date — stamps the signed date in ISO format
text — stamps the field value
checkbox — stamps a checked/unchecked glyph
- A Certificate of Completion page is appended. The certificate lists:
- Document title and ID
- Completion timestamp
- Every signer with their name, email, role, signed timestamp, and IP
- The complete audit trail (most recent 30 events) with timestamps and IPs
- The pre-certificate SHA256 hash of the stamped PDF — your tamper-evidence anchor
- The final hash of the signed-plus-certificate PDF is computed and stored on the document record (
finalPdfSha256)
- The signed PDF is uploaded to cloud storage under the document's versioned prefix
- A signed copy is automatically emailed to every signer and the document's creator
Integrity Verification
The Certificate of Completion embeds the SHA256 hash of the document content immediately before the certificate was appended. If anyone modifies the bytes of the final signed PDF, the certificate's embedded hash will no longer match a freshly computed hash of those bytes — making tampering detectable.
To verify a signed document hasn't been altered:
- Download the signed PDF from KarmaFlow
- Compute the SHA256 of the file
- Compare against the
finalPdfSha256 value on the document record (visible via API at GET /internal/document/documents/:id)
Public Signing URLs and Configuration
The public base URL for signing links is controlled by the PUBLIC_BASE_URL (or APP_BASE_URL) environment variable. Set it to whatever public hostname your KarmaFlow instance serves at. The signing-from email address is controlled by SIGNING_FROM_EMAIL and falls back to noreply@{your_mailgun_domain}.
Reminders and Resend
From any document in out_for_signature or partially_signed status, you can click Resend on a specific signer to re-issue their invite. This generates a fresh token (the previous one is invalidated by overwriting the hash) and sends a new email with the new link.
Voiding a Document
You can void any document before it reaches signed status. Voiding:
- Sets status to
voided
- Records the reason in the audit trail
- Invalidates all pending signing sessions (links stop working)
- Does not retract emails already sent — recipients will see "This signing session is no longer valid" if they click
A fully signed document cannot be voided. To revoke a signed agreement you'd execute a separate mutual termination — same as you would on paper.