API v3: embedded signing, webhooks, and idempotency
A cleaner REST surface, embedded signing that lives inside your own product, and webhook delivery you can actually rely on.
API v2 served us for four years. It also accumulated four years of decisions we would not make again: inconsistent pagination, webhooks that retried unpredictably, and an embedded signing flow that required a redirect nobody wanted. v3 is a clean surface, and v2 is not going anywhere for a long time.
Embedded signing without the redirect
The most requested change by a wide margin. In v2, embedding meant generating a URL and sending the user to it. Your product visibly handed off to ours, which is a strange experience when the whole point was to keep users inside your application.
v3 issues short-lived signing tokens scoped to a single recipient on a single envelope. You mount our embed in an iframe or use the JavaScript SDK, pass the token, and the signing experience renders inside your layout. Completion fires a callback in the parent frame rather than a page navigation.
Webhooks that behave
Webhook delivery in v2 was best-effort with an undocumented retry schedule, which meant most integrators built their own polling as a safety net. That is a bad outcome for everyone.
v3 webhooks are explicit about all of it:
- Retries follow published exponential backoff for up to 24 hours
- Every payload carries a unique event ID; redeliveries reuse it so you can dedupe
- Payloads are signed with HMAC-SHA256 over the raw body, with a timestamp to prevent replay
- A replay endpoint lets you re-request any event from the last 30 days
- The dashboard shows delivery history and failure reasons per endpoint
Verify the signature against the raw request body, before any JSON parsing. Parsing and re-serialising will change the bytes and the signature will not match — this is the single most common integration bug we see.
Idempotency
Every mutating endpoint accepts an idempotency key. Send the same key twice and you get the original response rather than a duplicate envelope. Keys are retained for 24 hours.
This matters more than it sounds. The failure mode without it is a network timeout on envelope creation, a retry from your side, and a counterparty receiving the same contract twice. Idempotency keys make that impossible.
Consistent pagination and errors
All list endpoints use cursor pagination with the same parameter names and the same response envelope. No more offset in one place and page tokens in another.
Errors return a stable machine-readable code alongside the human-readable message, plus a request ID. When you contact support with a request ID we can find the exact call in seconds.
Rate limits you can plan around
v2 rate limits were undocumented, which meant integrators discovered them in production. v3 publishes them, returns remaining quota on every response, and sends a Retry-After header when you exceed them.
Limits are per-account rather than per-key, so creating additional keys does not multiply your quota. If you have a legitimate need for higher throughput — a bulk migration, a seasonal peak — ask, and we will raise it rather than have you build workarounds.
Sandbox that behaves like production
Every account gets a sandbox environment with separate credentials. Sandbox envelopes are fully functional — you can create, send, sign, and complete them — but emails go only to addresses on your account, documents carry a visible watermark, and nothing counts against your plan.
Sandbox also lets you force conditions that are hard to reproduce naturally: simulate a bounce, a decline, an expiry, or a webhook delivery failure. Testing your error handling against real failure modes rather than hoping is the difference between an integration that degrades gracefully and one that silently drops envelopes.
Migration
v2 remains fully supported with no announced end date. When we do eventually deprecate it, the commitment is twelve months of notice minimum.
- 1Generate v3 credentials in the dashboard — they are separate from v2 keys
- 2Point a non-production environment at v3 and run your existing test suite
- 3Move webhook endpoints one event type at a time; both versions can be active simultaneously
- 4Switch embedded signing last, since it is the most user-visible change
Designing your side of the integration
A few patterns that consistently separate integrations that age well from ones that need rewriting.
- Treat webhooks as the source of truth for state changes, and polling as a reconciliation safety net rather than the primary mechanism
- Store our envelope ID against your own record immediately on creation, before you do anything else
- Make your webhook handler idempotent and fast — acknowledge, queue, process asynchronously
- Never assume events arrive in order; use the event timestamp rather than arrival order
- Log the request ID from every API response so support conversations start with evidence
The ordering point catches people. Networks being what they are, a "completed" event can arrive before the "signed" event that preceded it. Handlers that assume sequence will occasionally process a completion against a record they think is still in progress.
Full reference documentation, OpenAPI schema, and SDKs for TypeScript, Python, Ruby, and Go are available now.
Jordan leads engineering at SignTheDoc. Before this he built payment infrastructure, which is where he learned to care about audit trails.