Docusign eSignature
The Docusign connector reaches the eSignature REST API v2.1 for one account. It is good for the read side of a signing workflow: which envelopes moved this week, who has signed and who has not, what documents an envelope contains, and what the audit trail says. It can also create and send an envelope, but that action ships switched off and approval-gated, because sending an envelope emails real people asking them to sign something.
What you need
Docusign has no API keys. Every call is authenticated with an OAuth access token, so you register your own integration and let the gateway obtain tokens from it.
1. Register an integration key. In Docusign Admin, open Settings → Apps and Keys (the developer sandbox equivalent is the Apps and Keys page of your demo account) and choose Add App and Integration Key. Name the app, then:
- Under Authentication, add a secret key. The gateway's OAuth flow takes a client id and a client secret, and applies PKCE on top of them where the connector's manifest records that the provider supports it.
- Under Redirect URIs, add
http://127.0.0.1:7376/oauth/callbackfor a gateway running on your own machine, orhttps://<your-gateway-host>/oauth/callbackfor a tunnelled gateway. Docusign rejects any redirect that is not registered here, exactly. - Copy the Integration Key. That is your OAuth client id.
2. Request the least privilege you need. For this connector that is signature, which grants the eSignature API and nothing else. Ask for extended alongside it: that is what gives you a refresh token the gateway can keep renewing, rather than one that expires with the access token, and the gateway will not seal a credential it cannot refresh.
3. Find your account base URI and account id. Both are on the same Apps and Keys page, under My Account Information: the API Account ID is the account id every capability takes, and the Account's Base URI (something like https://na3.docusign.net) is what the connection's base URL is built from. Note them before you go any further — the base URL is set when you create the connection, which happens before the OAuth flow runs.
The userinfo endpoint returns the same pair, as account_id and base_uri on the entry of the accounts array with "is_default": true, if you would rather read them from a script. It needs an access token of its own, though; under the flow below the gateway holds the tokens, not you.
# Sandbox. For production, use https://account.docusign.com/oauth/userinfo
curl -s https://account-d.docusign.com/oauth/userinfo \
-H "Authorization: Bearer $DS_ACCESS_TOKEN"
The connector ships pointed at the developer sandbox, https://demo.docusign.net/restapi. That is deliberate: if you forget to change it, calls land in the sandbox rather than sending real signature requests.
For production, set the connection's base URL to your own base_uri with /restapi appended, for example https://na3.docusign.net/restapi. Nothing else works: Docusign returns 401 if you call an account through the wrong account server, and the gateway pins the host, so an agent cannot reach a different one.
The authorisation server moves with it. The sandbox issues tokens from account-d.docusign.com, production from account.docusign.com, and a demo token is not accepted by a production account server. The oauth block in this connector's manifest names the sandbox pair, matching the default base URL — and unlike the base URL, those endpoints come from the manifest rather than from the connection, so changing one connection's base URL to production leaves its OAuth flow authorising against the demo server and the token it seals will be refused.
For production, install a second copy of the manifest under its own id: take docusign.json, change "id" to something like docusign-production, point both oauth URLs at account.docusign.com, POST it to /v1/connectors/install, and create the connection from that. The two then sit side by side in the catalog with separate credentials.
Gateway 1.1.0 and later runs the whole authorisation code flow itself, against the integration key you just registered. You start it, approve once in a browser, and the gateway exchanges the code, seals the access token, refresh token and client secret as the connection's credential, and from then on refreshes the access token on its own — two minutes before each eight-hour token runs out, on the invoke path. Nothing to re-paste, nothing to babysit. permaura.com is never involved and never sees any of it.
What is not there yet is a Sign in with Docusign button: permaura.com's connector OAuth endpoint still answers with a "rolling out" response. Today you start the flow through the gateway's own REST API, as below.
Add the connection
Both halves of this are gateway-side today. The console's Add connection dialog will not create a connection without a credential, it has no field for the per-account base URI you need here, and the OAuth path it offers sends your client id and secret to permaura.com rather than to your gateway. So create the connection against the gateway, pinning your own account's base URI as you go:
BASE=http://127.0.0.1:7376
curl -s -X POST $BASE/v1/connections/from-preset \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' -d '{
"preset_id": "docusign",
"name": "docusign-live",
"base_url": "https://na4.docusign.net/restapi"
}'
The response echoes the host it pinned, so you can check it took, and carries the connection_id used below. Then start the flow with an operator token:
curl -s -X POST $BASE/v1/connections/$CONNECTION_ID/oauth/start \
-H "authorization: Bearer $TOKEN" \
-H 'content-type: application/json' -d '{
"client_id": "…your integration key…",
"client_secret": "…your secret key…",
"redirect_uri": "http://127.0.0.1:7376/oauth/callback",
"scopes": ["signature", "extended"]
}'
The response carries an authorize_url. Open it in a browser and approve. Docusign redirects back to your gateway, which finishes the exchange and shows a plain "Connected" page. The credential is sealed on your gateway and never displayed again. Nothing can use it until a grant allows it.
Four things to watch:
redirect_urihas to match what you registered with Docusign, exactly. The gateway asks for it rather than guessing, because a mismatch is the most common way this fails. Loopback addresses (http://127.0.0.1:7376/oauth/callback,http://localhost:…) may be plain http; anything else has to be https.- The authorize link is single-use and expires after ten minutes. Start again if it goes stale.
- No refresh token, no credential. If Docusign returns an access token without a refresh token, the gateway refuses the exchange rather than sealing something that dies in eight hours, and the error says so. That is what the
extendedscope is for. - Run it from the gateway's own host if you have a device enrolled for approvals. Sealing a credential changes the upstream identity the connection acts as, so it is held for a device signature, and a browser redirect cannot carry one. Starting the flow over a tunnel or the broker is refused in that setup.
What the agent can do
Every capability takes accountId as a path parameter, so give the agent the API account id you noted in step 3.
| Action | What it does | On by default |
|---|---|---|
envelopes.list | Lists envelopes changed in a date range | Yes |
envelopes.read | Reads the status of one envelope | Yes |
recipients.list | Lists an envelope's recipients and their status | Yes |
documents.list | Lists the documents in an envelope | Yes |
documents.download | Downloads one document as PDF | Yes |
templates.list | Lists templates | Yes |
templates.read | Reads one template | Yes |
audit_events.list | Reads an envelope's audit trail | Yes |
envelopes.send | Creates an envelope and emails it to its recipients | No, and needs approval |
envelopes.send is the only write. It is off on connect, and switching it on still leaves every call waiting for a human approval, because a sent envelope cannot be unsent: the recipients already have the email. The same capability also creates drafts, by setting the status body parameter to created instead of sent. The approval gate applies either way, since only the arguments tell the two apart.
Good to know
envelopes.listneedsfrom_date. Docusign requires it unless you filter by envelope or transaction ids, which this connector does not expose. An agent that calls it with no arguments gets a 400. ISO 8601 with an explicit time zone offset is the format Docusign recommends.- Sandbox and production are separate worlds. Demo accounts, integration keys and envelopes do not carry across. Docusign also requires a go-live review before an integration key works against production, so expect to test everything on
demo.docusign.netfirst. - The JWT grant is the other way to run unattended, and Permaura does not implement it. Docusign's JWT grant needs no browser step at all, which is why it is the usual choice for a service integration. The gateway runs the authorisation code grant instead: one browser approval when you connect, and refreshes on its own after that. If you need the JWT grant specifically, you are outside what this connector does today.
- Rate limits. 3,000 API calls per hour per account by default, plus a burst limit of 500 calls in any 30 seconds. Over either and you get a 429 telling you when you can resume. Watch the
X-RateLimit-Remainingand burst headers. documents.downloaddoes not hand the file to the agent. Docusign answers it with a PDF byte stream, and the gateway passes connector responses to agents as JSON, so a successful call comes back empty. It tells you the document exists and is retrievable; it does not put the contract in front of the model. ThedocumentIdcan be a real document id or one of Docusign's special values:combined(every document in one PDF),archive(a ZIP),portfolio(a PDF portfolio), orcertificate(the certificate of completion). To read a document yourself, call the same URL outside Permaura.- Most identifying details are redacted, but not every name. Email addresses, first, last and full names, sender and in-person-signer names, phone and fax numbers, IP addresses, signer access codes and client user ids are replaced before the agent sees them. A recipient's
namefield is not, and that is deliberate: redaction matches on field name anywhere in a response, andnameis also what Docusign calls a template and a document, so blanking it would blank the very thingstemplates.listanddocuments.listexist to return. Assume an agent withrecipients.listcan see who an envelope went to. Audit trails are outside redaction's reach for the same kind of reason:audit_events.listreturns generic name/value pairs rather than named fields. - The account id is not part of the pinned host. Pinning the base URL stops an agent reaching a different Docusign server, but an agent that knows another
accountIdon the same server could try it. Only hand out the account id you intend it to use.