E-Signature API Guide: How It Works, Embed vs Redirect, Webhooks and Pricing
Every e-signature API does the same five things: take a document, attach signers and fields, produce a signing session, tell you when it is done, and hand you the sealed file. The differences are in how the signing session reaches the user, how reliably you learn about completion, and what you pay per document. This guide walks through each, using ShockSign's REST API for the examples. The endpoints shown are real; see the API docs for the full reference.
The five-step lifecycle
- Create a document. Upload a PDF or Word file, or instantiate one from a template you built in the dashboard.
- Add signers and fields. Who signs, in what order, and where the signature, initials, date and text fields sit.
- Send. The platform creates a signing session for each signer and either emails them a link or returns the link to you.
- Get notified. Webhooks tell your system when the document is viewed, signed, completed or declined.
- Retrieve the result. Download the sealed PDF and its audit trail, and store or display it.
If an API cannot do all five without a human in the dashboard, it is not an API for automation; it is a dashboard with an import button.
Authentication
ShockSign uses API keys. Create one under API keys in your account (Professional and Business plans), and pass it in the X-API-Key header. The base URL is https://shocksign.com/api. Keys are shown once at creation, can be revoked at any time, and every key creation and revocation is written to your audit log.
curl -X GET "https://shocksign.com/api/documents" \
-H "X-API-Key: sk_your_api_key"
Requests are rate-limited, so cache document state on your side and rely on webhooks rather than polling.
Step 1: create a document
Upload a file with a multipart form. PDF, DOC and DOCX are accepted, up to 25 MB.
curl -X POST "https://shocksign.com/api/documents" \
-H "X-API-Key: sk_your_api_key" \
-F "file=@contract.pdf" \
-F "title=Service Agreement"
# {
# "id": "doc_abc123",
# "title": "Service Agreement",
# "status": "draft",
# "createdAt": "2026-09-19T10:30:00Z"
# }
For recurring documents, build the template once in the dashboard with fields already placed, then list your templates with GET /templates and create documents from them. That keeps field placement out of your code.
Step 2: signers and fields
Add each signer with a name and email using POST /documents/:id/signers, list them with GET /documents/:id/signers, and remove one from a draft with DELETE /documents/:id/signers/:signerId. Signing order is either sequential, where each signer is notified only after the previous one completes, or parallel, where everyone is notified at once. When you use templates, the fields are already defined.
Step 3: send, and choose embed or redirect
POST /documents/:id/send moves the document out of draft, emails each signer (with an optional custom message), and returns a signing URL per signer:
{
"message": "Document sent for signature",
"signatureRequests": [
{
"id": "req_...",
"signerEmail": "jane@example.com",
"signerName": "Jane Doe",
"signingUrl": "https://shocksign.com/sign/<token>",
"order": 1
}
]
}
Now the design decision. There are two ways to get that URL in front of the signer.
Redirect (hosted signing)
Send the user to the signing URL, or let the email do it. ShockSign hosts the signing page, handles verification codes, field validation, mobile layout and the legal notices, and emails the completed copy. Choose this when the signer is not already logged into your app (customers, counterparties, one-off signers), when you want the least code, or when you want the platform's own domain and notices to carry the legal weight.
Embed (iframe signing)
Place the signing page inside your own app in an iframe pointed at https://shocksign.com/embed/sign/<token> (the dashboard's Integrations page generates the snippet, with a light or dark theme), and listen for postMessage events from it. The embedded page posts messages with source: "shocksign" and a type of ready, loaded, signed, declined, validation_error, already_processed or error, so your page can advance the user without a reload:
window.addEventListener("message", (e) => {
if (e.data?.source !== "shocksign") return;
if (e.data.type === "signed") showNextStep();
if (e.data.type === "declined") showDeclined(e.data.reason);
});
Choose embed when the signer is already inside your product (onboarding, checkout, a dealer or patient portal), when you want the flow to feel native, or when you need to gate the next step on completion. Do not treat the browser event as the source of truth for your records; confirm with the webhook or by fetching the document.
If you do not want to write any code, the dashboard's embedded signature forms give you a copy-and-paste embed for a standalone form.
Step 4: webhooks
Register an endpoint with POST /webhooks, subscribing to any of document.created, document.sent, document.viewed, document.signed, document.completed and document.declined. List with GET /webhooks, remove with DELETE /webhooks/:id, and fire a test delivery from the dashboard before going live.
Each delivery is a JSON POST shaped as { "event": "...", "timestamp": 1789811400000, "data": { ... } }, with three headers:
X-ShockSign-Event: the event name.X-ShockSign-Timestamp: the Unix time in milliseconds the delivery was generated.X-ShockSign-Signature: an HMAC-SHA256 of the raw JSON body, keyed with your webhook secret, hex encoded.
Verify every delivery before acting on it:
const crypto = require("crypto");
function verify(rawBody, header, secret) {
const expected = crypto.createHmac("sha256", secret)
.update(rawBody).digest("hex");
return expected.length === header.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
Compute the HMAC over the raw request body exactly as received, not a re-serialized object. Respond with a 2xx quickly and do the real work asynchronously; the delivery times out after 30 seconds. Reject deliveries whose timestamp is far from your clock to blunt replay attempts, and make your handler idempotent on the document ID and event, because any webhook system can deliver twice.
Step 5: retrieve the result
GET /documents/:id returns the document with each signer's status. GET /documents/:id/download returns the sealed PDF as binary once it is complete. The audit trail and certificate of completion are available per document as well. Store the PDF and certificate in your own system of record; the platform keeps them too, but your records should not depend on anyone's uptime.
Sandbox and testing
Test against a separate ShockSign account with its own API key so test documents never mix with production. Send documents to your own addresses, walk through hosted and embedded signing on a phone, and confirm your webhook handler sees document.viewed, document.signed and document.completed in that order. Every plan includes a full audit trail, so you can inspect what the platform recorded for each test.
Pricing models for e-signature APIs
There are three common models, and they produce very different bills.
- Per envelope or per API call. You pay for each send. Predictable at low volume, expensive at scale, and it punishes retries and tests.
- Developer or Enterprise tier. API access gated behind a higher plan or a sales contract, sometimes with per-seat charges on top. This is DocuSign's usual path; as of 2026, check current terms.
- Per account with a document allowance. A flat monthly price that includes the API and a number of documents. This is how ShockSign prices: Professional at $29/month includes API access, 50 documents a month, 10 templates and 5 team members; Business at $99/month includes the full API with unlimited documents, templates and team members plus priority support. Month-to-month, yearly optional.
To compare, take your expected monthly volume and compute the effective cost per completed document under each model. Include test sends and re-sends in the estimate; they are documents too.
Design checklist
- Use templates for anything sent more than once; keep field coordinates out of your code.
- Prefer webhooks over polling; keep a fallback job that reconciles stale documents by fetching them.
- Verify the HMAC signature on every webhook with a constant-time comparison.
- Make handlers idempotent; expect duplicates and out-of-order arrival.
- Store the completed PDF and certificate in your own storage.
- Use redirect for strangers, embed for logged-in users, and never trust the browser as the record.
- Rotate API keys on staff changes; each key's creation and revocation is logged.
The full endpoint reference is at /api-docs, and the e-signature API page covers CRM and workflow use cases.
Frequently asked questions
How does an e-signature API work?
You upload or generate a document, attach signers and fields, and call send. The platform creates a signing session per signer and returns or emails a signing URL. Webhooks notify your system as the document is viewed, signed and completed, and you download the sealed PDF and audit trail when it is done.
Should I embed the signing page or redirect to it?
Redirect (hosted signing) when the signer is not logged into your app or you want minimal code. Embed (iframe) when the signer is already inside your product and you want to advance the flow on completion. In both cases confirm completion with a webhook or by fetching the document, not the browser event alone.
How do I verify a ShockSign webhook?
Compute an HMAC-SHA256 of the raw request body using your webhook secret, hex encode it, and compare it in constant time to the X-ShockSign-Signature header. Also check X-ShockSign-Timestamp against your clock and make your handler idempotent.
Which webhook events are available?
document.created, document.sent, document.viewed, document.signed, document.completed and document.declined. Each delivery includes the event name in X-ShockSign-Event and a JSON body with event, timestamp and data.
How much does ShockSign's API cost?
API access is included on Professional at $29 per month (50 documents, 10 templates, 5 team members) and Business at $99 per month (unlimited documents, templates and team members). There is no separate developer plan and no annual contract.
Is there a sandbox?
Use a separate ShockSign account with its own API key for testing so test documents stay out of production. Send to your own addresses and confirm your webhook handler receives each event before going live.
Try ShockSign free
Start on the free plan (1 document, 7-day trial) or take a 7-day trial of Professional. No credit card, no annual contract.
See pricingCreate a free account