Embedded Signing
Embedded signing lets you integrate the inSigner signing experience directly into your web application using an iframe. Your users sign documents without leaving your app.
How it works
Section titled “How it works”- Create a document with signers via the API
- Retrieve the signer’s unique signing URL
- Embed that URL in an iframe in your app
- Listen for completion via webhooks or
postMessage
Step-by-step integration
Section titled “Step-by-step integration”-
Create and configure the document
Create a document, upload the PDF, add fields and signers as usual:
// Create documentconst { data: doc } = await insignerFetch('/documents', {method: 'POST',body: JSON.stringify({name: 'Service Agreement',signingType: 'sequential'})});// Upload PDFconst { data: upload } = await insignerFetch(`/documents/${doc.id}/upload`, {method: 'POST',body: JSON.stringify({filename: 'agreement.pdf',contentType: 'application/pdf',fileSize: 125000})});await fetch(upload.uploadUrl, {method: 'PUT',body: pdfBuffer,headers: { 'Content-Type': 'application/pdf' }});// Add fieldsawait insignerFetch(`/documents/${doc.id}/fields`, {method: 'POST',body: JSON.stringify({type: 'signature',label: 'Your Signature',page: 1,x: 100, y: 650,width: 200, height: 60,assignedTo: 0})});// Add signerconst { data: signer } = await insignerFetch(`/documents/${doc.id}/signers`, {method: 'POST',body: JSON.stringify({name: 'Current User',role: 'signer',order: 0})}); -
Send the document
const { data: sent } = await insignerFetch(`/documents/${doc.id}/send`, {method: 'POST'}); -
Get the signing URL
After sending, retrieve the document details to get the signer’s signing URL:
const { data: details } = await insignerFetch(`/documents/${doc.id}`);// The signing URL is available on each signerconst signingUrl = details.signers[0].signingUrl; -
Embed in an iframe
<iframeid="insigner-frame"src="SIGNING_URL_HERE"width="100%"height="800"frameborder="0"allow="camera"style="border: 1px solid #e2e8f0; border-radius: 8px;"></iframe> -
Listen for completion
Use webhooks to detect when the signer completes:
// In your webhook handlerapp.post('/webhooks/insigner', (req, res) => {const event = req.body;if (event.event === 'signer.completed') {const { document_id, signer } = event.data;// Notify your frontend via WebSocket, SSE, or pollingnotifyClient(signer.email, document_id, 'completed');}res.status(200).json({ received: true });});
Frontend example
Section titled “Frontend example”Here’s a complete React component for embedded signing:
import { useState, useEffect } from 'react';
function EmbeddedSigning({ signingUrl, onComplete }) { const [status, setStatus] = useState('signing');
return ( <div style={{ width: '100%', maxWidth: '900px', margin: '0 auto' }}> {status === 'signing' && ( <> <h2>Please review and sign the document</h2> <iframe src={signingUrl} width="100%" height="800" frameBorder="0" allow="camera" style={{ border: '1px solid #e2e8f0', borderRadius: '8px', }} /> </> )}
{status === 'completed' && ( <div style={{ textAlign: 'center', padding: '60px 20px' }}> <h2>✅ Document signed successfully!</h2> <p>You'll receive a copy by email.</p> </div> )} </div> );}Security considerations
Section titled “Security considerations”- Generate URLs server-side. Never expose your API key to the frontend.
- Use one URL per signer. Each URL is unique and can only be used by the intended signer.
- Set expiration dates. Documents expire after 180 days by default. For embedded signing, consider setting a shorter expiration.