Back to API Docs
Embed Widget

Embed Signing Widget

Drop a signing experience into your app with a single JavaScript call. Works with any framework or plain HTML.

How It Works

1

Create envelope via API

Use POST /api/v1/envelopes to upload a PDF and add recipients.

2

Get embed URL

Call POST /api/v1/envelopes/{id}/embed-url to get a time-limited signing URL.

3

Open in your app

Use SignForge.open() to launch the signing UI as an inline iframe or modal overlay.

Get Embed URL

After creating an envelope and sending it, request an embed URL for a specific recipient:

bash
curl -X POST https://signforge.io/api/v1/envelopes/{envelope_id}/embed-url \
  -H "X-API-Key: sf_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"recipient_index": 0}'

Response

json
{
  "embed_url": "https://signforge.io/embed/sign/eyJhbGciOiJIUz...",
  "token_expires_at": "2026-04-24T12:00:00Z"
}

The embed URL contains a time-limited signing token. Generate a fresh URL each time a user needs to sign.

Install the JavaScript SDK

Add a single script tag to your page. No npm package or build step required.

html
<script src="https://signforge.io/signforge-embed.js"></script>

The SDK exposes a global SignForge object.

Container Mode (Inline)

Embed the signing UI inline within a specific element. Great for multi-step wizards or custom layouts.

html
<div id="sign-here" style="width: 100%; height: 700px;"></div>

<script>
  SignForge.open({
    url: "https://signforge.io/embed/sign/{token}",
    container: "#sign-here",
    onSigned: (data) => {
      document.getElementById("sign-here").innerHTML =
        "<p>Signed successfully!</p>";
    },
  });
</script>

The iframe will fill the container element. Set an explicit height for best results.

postMessage Events

The embed iframe communicates with the parent window via postMessage. If you prefer to listen directly instead of using the SDK:

Event TypeDataWhen
signforge:ready{ envelope_id }Signing UI is loaded and interactive
signforge:signed{ envelope_id, signed_at }Signer completed all fields and submitted
signforge:error{ message }An error occurred (network, validation)
signforge:expired{}Signing token has expired

Direct listener example

javascript
window.addEventListener("message", (event) => {
  // Always verify origin
  if (!event.origin.includes("signforge.io")) return;

  const { type, ...data } = event.data;
  switch (type) {
    case "signforge:signed":
      console.log("Signed!", data.envelope_id);
      break;
    case "signforge:error":
      console.error("Error:", data.message);
      break;
  }
});

SDK Reference

SignForge.open(options)

Opens the signing UI. Returns void.

OptionTypeDescription
urlstringRequired. The embed URL from the API.
containerstring | nullCSS selector for inline mode. Null or omit for modal.
onReadyfunctionCalled when the signing UI is loaded.
onSignedfunctionCalled when signing is completed.
onErrorfunctionCalled on errors.
onExpiredfunctionCalled when the signing link expires.

SignForge.close()

Closes the signing UI (removes iframe and overlay). Safe to call at any time.

Framework Examples

React / Next.js

tsx
import { useEffect } from "react";
import Script from "next/script";

export default function SignPage({ embedUrl }: { embedUrl: string }) {
  return (
    <>
      <Script
        src="https://signforge.io/signforge-embed.js"
        onLoad={() => {
          (window as any).SignForge.open({
            url: embedUrl,
            container: "#sign-container",
            onSigned: () => {
              alert("Document signed!");
            },
          });
        }}
      />
      <div id="sign-container" style={{ height: 700 }} />
    </>
  );
}

Plain HTML

html
<!DOCTYPE html>
<html>
<head>
  <title>Sign Document</title>
  <script src="https://signforge.io/signforge-embed.js"></script>
</head>
<body>
  <h1>Please sign below</h1>
  <div id="sign-here" style="width:100%;height:700px;border:1px solid #ccc;border-radius:8px;"></div>

  <script>
    SignForge.open({
      url: "EMBED_URL_FROM_API",
      container: "#sign-here",
      onSigned: function(data) {
        document.getElementById("sign-here").innerHTML =
          "<h2>Thank you!</h2><p>Document signed successfully.</p>";
      }
    });
  </script>
</body>
</html>

Content Security Policy

If your site uses a Content Security Policy, add SignForge to your allowed sources:

text
frame-src https://signforge.io https://staging.signforge.io;
script-src https://signforge.io;

The embed iframe loads from /embed/sign/* paths. No cookies or third-party scripts are loaded inside the iframe.

Branding

Free & Pro

Shows “Powered by SignForge” text at the bottom of the embed.

Business & Enterprise

Branding removed. Clean white-label signing experience.

API Reference

Full REST API documentation with endpoint reference.

MCP Server

Use SignForge from Claude Desktop and AI agents.

Code Examples

Integration samples for n8n, Retool, cURL, and more.