Docs

#Approvals in DocuSign

Some decisions need more than a click. When the verdict has to stand up later, to a regulator, a counterparty, or your own auditor, you can bind it to a signed DocuSign envelope instead of a button.

The decision resolves when the envelope does. A completed signature approves it; a declined or voided envelope rejects it. Either way the verdict carries the envelope it came from.

A signed document is the one approval a policy can require: tick Requires a signed document (DocuSign) on the policy and every request under it must attach its envelope. See Requires a signed document.

#Reference mode: you create the envelope, we receive the outcome

Ratifia is a pure receiver. It does not create envelopes, mint signing URLs, or hold an OAuth connection to your DocuSign account. Your system creates the envelope in your own account, exactly as it does today, and tells Ratifia the envelope id when it asks for the decision.

That has a useful consequence: there is nothing to certify. You do not need a DocuSign integration key, and you do not need to take an app through DocuSign's go-live review. You point Connect at us and you are done.

#DocuSign decisions are exclusive

A decision with an envelope can only be decided by that envelope. The app, email links, Slack and Discord still show it and link to it, but a vote from any of them is refused (the app and API with 403 exclusive_surface).

That is deliberate. The point of a signed approval is that it cannot be substituted with a click. It also means a broken Connect configuration leaves the decision with no way to resolve, so get the setup confirmed before you rely on it. See Troubleshooting below.

#What you need in DocuSign

Configuring Connect is an account administrator function in DocuSign. If Admin → Integrations → Connect is not visible to you, you do not have the required access and will need someone on your account who does. Ratifia needs no permissions in your DocuSign account at all; it never calls DocuSign.

#Setting it up

#1. Get your webhook URL

In Ratifia, go to Settings → DocuSign. The page shows the URL to give DocuSign. Copy it from there rather than typing it. It is built from the API host for the environment you are signed in to, so copying guarantees you get the right one.

#2. Create a Connect configuration

In DocuSign: Admin → Integrations → Connect → Add Configuration → Custom.

SettingValue
URL to publishthe URL from Settings → DocuSign
Data formatJSON
Include HMAC signatureenabled (see below)
EventsEnvelope Completed, Declined, Voided

Data format must be JSON. Ratifia parses the Connect payload as JSON; an XML payload cannot be read, so the callback is discarded and the decision never resolves. This is the most common setup mistake and it fails silently.

Which events. Those three are the terminal ones and the only ones that move a decision:

Envelope statusDecision becomes
completedApproved
declinedRejected
voidedRejected

Anything else, such as sent, delivered, or a single recipient signing, is treated as not-yet-final: Ratifia acknowledges it and keeps waiting. You can subscribe to those events safely, but they do nothing, so leaving them off keeps the traffic down.

#3. Turn on HMAC and save the key

Ratifia requires a signed callback. Enable Include HMAC Signature on the configuration and add a key; DocuSign shows the secret once.

Without it, every callback is rejected with 401. The endpoint is public by route, so the signature is the only thing standing between your decisions and anyone who can guess a URL.

Paste that secret into Settings → DocuSign in Ratifia and save. It is encrypted at rest and never readable back; the page will simply start reporting that a key is configured.

Key rotation is safe. DocuSign signs each payload with every key on the configuration, and Ratifia accepts a match against any of them. So you can add a new key, update Ratifia, and remove the old one without dropping a callback.

#Requesting a decision against an envelope

Create the envelope in your own account first, then reference it when you ask for the decision. Passing docusign makes the signature the approval:

json
POST /v1/worker/decisions{  "engine": "inngest",  "externalRunId": "run_123",  "stepRef": "countersign-contract",  "prompt": "Counterparty returned the signed MSA. Countersign?",  "docusign": {    "envelopeId": "8f2c...",    "accountId": "optional, your DocuSign account id",    "documentUrl": "https://... the link you sent the signer"  }}

The envelope id is what correlates the callback back to the decision. Ratifia stores it when the decision is created and matches inbound events against it. An envelope Ratifia has never been told about is acknowledged and ignored, so create the decision before the envelope is signed, not after.

documentUrl is optional and is only a deep link for the reviewer to click through to sign. In reference mode Ratifia does not mint signing URLs; pass the one you already sent. It must be http(s), and it is the only place the envelope link is read from. Records the signer may want to consult go in a links block; documentUrl is the thing to sign.

#Multiple environments from one DocuSign account

A Connect configuration points at exactly one URL, but an account can hold several configurations, so you do not need a second DocuSign account to run staging and production side by side. Create one configuration per environment, each with its own URL and its own HMAC key.

Every configuration fires on every envelope in the account, so both environments receive every event. That is harmless: each only acts on envelope ids it has a decision for, and acknowledges the rest. Naming your envelopes for the environment they belong to makes the DocuSign side easier to read.

Use a separate HMAC key per configuration. Sharing one key means a compromise of the weaker environment can forge verdicts in the stronger one.

#Troubleshooting

SymptomLikely cause
Callbacks rejected, 401HMAC not enabled on the configuration, or the key in Ratifia does not match one on it
Callbacks accepted, decision never resolvesData format is XML, not JSON
Decision never resolves, no callback at allThe configuration's URL points at a different environment
Envelope completed but nothing happenedThe decision was created without the envelopeId, so there was nothing to correlate against, or it was created after the envelope was already signed
Reviewer cannot approve from the InboxExpected. DocuSign decisions are exclusive and bind only via the signature

A quick way to prove the wiring before anyone signs: temporarily subscribe to Envelope Sent as well. It is not a terminal event, so the decision stays pending, but you will get a callback the moment an envelope goes out, which confirms the URL, the HMAC key and the JSON format in one go. Turn it back off once you have seen it arrive.