Embedded Signing
Embedded signing lets your users sign documents without leaving your application. Instead of redirecting to VisiSign, you embed the signing experience in an iframe — either inline on the page or in a modal overlay.
How it works
Section titled “How it works”- Your app creates a signature request via the API.
- The API returns a
signing_urland anembed_urlfor each signer. - You load the
embed_urlin an iframe using the JavaScript SDK. - The signer completes signing inside your app.
- The SDK fires a
signedevent viapostMessage, and your webhook receives the completion notification.
The embed_url points to a streamlined signing view with no VisiSign navigation — just the document and signing fields.
Prerequisites
Section titled “Prerequisites”- An API key (Getting Started)
- The VisiSign embed SDK loaded on your page
Install the SDK
Section titled “Install the SDK”Add the script tag to your page:
<script src="https://app.visisign.app/embed.js"></script>The script is 1.3KB gzipped, has zero dependencies, and attaches VisiSign to window.
Get the embed URL
Section titled “Get the embed URL”When you create a signature request, the response includes signing_url and embed_url for each signer:
{ "signature_request": { "id": "sr_789", "status": "sent", "signers": [ { "id": "sig_101", "name": "Jane Smith", "email": "jane@example.com", "signing_url": "https://app.visisign.app/sign/tok_abc123", "embed_url": "https://app.visisign.app/embed/sign/tok_abc123" } ] }}Inline embedding
Section titled “Inline embedding”Render the signing flow inside a container element on your page:
<div id="signing-container" style="width: 100%; height: 600px;"></div>
<script> const signer = VisiSign.embed({ url: 'https://app.visisign.app/embed/sign/tok_abc123', container: '#signing-container', });
signer.on('ready', (data) => { console.log('Signing loaded:', data.documentTitle); });
signer.on('signed', (data) => { console.log('Document signed!'); // Update your UI, redirect, etc. });
signer.on('declined', (data) => { console.log('Signer declined'); });
signer.on('error', (data) => { console.error('Signing error:', data.code, data.message); });</script>The container option accepts a CSS selector string or a DOM element.
Call signer.destroy() to remove the iframe and clean up event listeners.
Modal embedding
Section titled “Modal embedding”Open signing in a centered modal overlay:
const signer = VisiSign.modal({ url: 'https://app.visisign.app/embed/sign/tok_abc123',});
signer.on('signed', (data) => { // Modal shows a brief confirmation, then you can close it setTimeout(() => signer.close(), 2000);});
signer.on('declined', (data) => { signer.close();});The modal includes:
- A semi-transparent dark overlay
- A centered container (max 700px wide, 90vh tall)
- A close button in the top-right corner
- ESC key to close
- Click outside to close
- Full-screen on mobile (under 640px)
Call signer.close() to dismiss the modal programmatically.
Events
Section titled “Events”All events are received via the .on() method. Event handlers are chainable:
signer .on('ready', handler) .on('signed', handler) .on('declined', handler) .on('error', handler);| Event | Data | Description |
|---|---|---|
ready | { signerId, documentTitle } | The signing session loaded and is ready |
signed | { signerId, documentTitle } | The signer completed signing |
declined | { signerId } | The signer declined to sign |
error | { code, message } | An error occurred (expired link, invalid token, etc.) |
Use .off(event) to remove all handlers for an event, or .off(event, handler) to remove a specific handler.
Branding
Section titled “Branding”The embedded signing view uses your organization’s branding (logo and brand color) from your VisiSign settings.
| Plan | Branding |
|---|---|
| Team | Full white-label — no VisiSign branding shown |
| API-only | Full white-label — no VisiSign branding shown |
| Free | Shows a small “Powered by VisiSign” link in the header |
Combining with webhooks
Section titled “Combining with webhooks”Embedded signing works alongside webhooks. The postMessage events tell your frontend that signing happened, while webhooks notify your backend:
Frontend (postMessage) Backend (webhook)──────────────────── ────────────────────signed event fires → signature_request.signed ↓ ↓Update UI immediately Update database Download signed PDF Trigger next workflow stepUse postMessage events for immediate UI updates. Use webhooks for reliable backend processing.
SDK reference
Section titled “SDK reference”VisiSign.embed(options)
Section titled “VisiSign.embed(options)”| Option | Type | Description |
|---|---|---|
url | string | The embed_url from the create response (required) |
container | string | HTMLElement | CSS selector or DOM element (required) |
Returns a SignerInstance with .on(), .off(), and .destroy() methods.
VisiSign.modal(options)
Section titled “VisiSign.modal(options)”| Option | Type | Description |
|---|---|---|
url | string | The embed_url from the create response (required) |
Returns a ModalInstance with .on(), .off(), .destroy(), and .close() methods.
Example: full flow
Section titled “Example: full flow”// 1. Your backend creates a signature request and returns the embed_urlconst response = await fetch('/api/create-signing', { method: 'POST' });const { embed_url } = await response.json();
// 2. Open the signing modalconst signer = VisiSign.modal({ url: embed_url });
// 3. Handle completionsigner.on('signed', () => { // Show success in your app document.getElementById('status').textContent = 'Signed!'; setTimeout(() => signer.close(), 2000);});
signer.on('declined', () => { signer.close(); document.getElementById('status').textContent = 'Declined';});
signer.on('error', (data) => { signer.close(); alert('Signing error: ' + data.message);});