Skip to content

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.

  1. Create a document with signers via the API
  2. Retrieve the signer’s unique signing URL
  3. Embed that URL in an iframe in your app
  4. Listen for completion via webhooks or postMessage
  1. Create and configure the document

    Create a document, upload the PDF, add fields and signers as usual:

    // Create document
    const { data: doc } = await insignerFetch('/documents', {
    method: 'POST',
    body: JSON.stringify({
    name: 'Service Agreement',
    signingType: 'sequential'
    })
    });
    // Upload PDF
    const { 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 fields
    await 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 signer
    const { data: signer } = await insignerFetch(`/documents/${doc.id}/signers`, {
    method: 'POST',
    body: JSON.stringify({
    email: 'user@example.com',
    name: 'Current User',
    role: 'signer',
    order: 0
    })
    });
  2. Send the document

    const { data: sent } = await insignerFetch(`/documents/${doc.id}/send`, {
    method: 'POST'
    });
  3. 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 signer
    const signingUrl = details.signers[0].signingUrl;
  4. Embed in an iframe

    <iframe
    id="insigner-frame"
    src="SIGNING_URL_HERE"
    width="100%"
    height="800"
    frameborder="0"
    allow="camera"
    style="border: 1px solid #e2e8f0; border-radius: 8px;"
    ></iframe>
  5. Listen for completion

    Use webhooks to detect when the signer completes:

    // In your webhook handler
    app.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 polling
    notifyClient(signer.email, document_id, 'completed');
    }
    res.status(200).json({ received: true });
    });

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>
);
}
  • 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.