Developer Guide

How to Embed Signing with createSigningUrl

To embed signing in your app: allow-list your domain, create an embedded request with createEmbeddedSignature, verify the signer, then call createSigningUrl to get a single-use URL and mount it in an iframe, redirect, or new tab.

No signing-request email is sent. The signer stays inside your product and is verified before the document opens.

10 min

Setup time

3 modes

Iframe / redirect / tab

Single-use

Short-lived URLs

SDK versions: the method names below are the embedded-signing surface of the TurboDocx SDK. Confirm the exact parameters for your SDK version against the SDK reference.

1

Allow-list your embedding domain

Embedding is deny-by-default. The signing page refuses to render in an iframe until you add your app's exact https origin to your allowed embedding domains in your embedded e-signature settings. This is the clickjacking control, so nothing can frame the signer's screen without your say-so.

allowed origins (E-Signature settings)
https://app.yourcompany.com

Local dev only: you may add an http://localhost origin to test, but remove every http:// origin and use https before production.

2

Create an embedded signature request

Call createEmbeddedSignature from your backend. Unlike sendSignature, it does not email a signing link, because you generate the URL yourself in step 4. Keep your API key on the server; it must never reach the browser.

create-embedded-request.ts
import { TurboSign } from '@turbodocx/sdk';
import { readFileSync } from 'fs';

TurboSign.configure({
  apiKey: process.env.TURBODOCX_API_KEY,
  orgId: process.env.TURBODOCX_ORG_ID,
  senderEmail: process.env.TURBODOCX_SENDER_EMAIL,
  senderName: process.env.TURBODOCX_SENDER_NAME,
});

// createEmbeddedSignature does NOT send a signing-request email.
const doc = await TurboSign.createEmbeddedSignature({
  file: readFileSync('contract.pdf'),
  documentName: 'Order Form',
  recipients: [
    { name: 'John Doe', email: 'john@example.com', signingOrder: 1 },
  ],
  fields: [
    {
      type: 'signature',
      recipientEmail: 'john@example.com',
      template: { anchor: '{signature1}', placement: 'replace' },
    },
  ],
});

const documentId = doc.documentId;
const recipientId = doc.recipients[0].id;
3

Verify the signer

Choose how to confirm the signer. Require a one-time passcode by email or SMS on the recipient, or, if your app already authenticated the signer through your own identity provider, assert that when you request the URL in step 4. Either way, the method is recorded on the certificate of completion.

recipient with a one-time passcode
recipients: [
  {
    name: 'John Doe',
    email: 'john@example.com',
    signingOrder: 1,
    // Require a one-time passcode before the document opens.
    verification: { method: 'email' }, // or 'sms' with a phone number
  },
],

Prefer your own identity provider? Skip the passcode and pass an identity assertion when you create the signing URL in the next step.

4

Request a single-use signing URL

When the signer is ready, call createSigningUrl with the document id and recipient. It returns a short-lived, single-use URL for that one signer. Generate it at the moment of signing, not ahead of time.

create-signing-url.ts
// Passcode / no external IdP:
const { url } = await TurboSign.createSigningUrl(documentId, {
  recipientId,
  returnUrl: 'https://app.yourcompany.com/signed',
});

// OR, if your app already verified the signer via your own IdP:
const { url: assertedUrl } = await TurboSign.createSigningUrl(documentId, {
  recipientId,
  identityAssertion: { verifiedBy: 'your-idp', subject: 'john@example.com' },
  returnUrl: 'https://app.yourcompany.com/signed',
});
5

Mount the signing URL

Send the URL to the browser and open it one of three ways. Use an iframe for a fully in-app experience, a redirect for the simplest integration, or a new tab when you want the signer to keep your app open behind them.

mount.tsx (iframe / redirect / new tab)
// 1) Iframe: signer never leaves your app
<iframe src={url} title="Sign document" width="100%" height="800" />

// 2) Redirect: simplest
window.location.href = url;

// 3) New tab
window.open(url, '_blank', 'noopener');

Blank iframe? The origin isn't allow-listed. Re-check step 1: the exact https origin hosting the iframe must be in your allowed embedding domains.

Related

Frequently Asked Questions

What is createSigningUrl?

createSigningUrl requests a short-lived, single-use URL that opens the TurboSign signing page for one recipient. You call it the moment a signer is ready, then mount the URL in an iframe, redirect to it, or open it in a new tab.

Do I need to send a signing email to embed signing?

No. Create the signature request with createEmbeddedSignature, which does not send a signing-request email, then generate a signing URL on demand with createSigningUrl. The signer never leaves your application.

How do I verify the signer's identity in an embedded flow?

Set a one-time passcode by email or SMS on the recipient, or, if your app already authenticated the signer, assert that identity when you request the signing URL. The method used is recorded on the certificate of completion.

Why is my embedded signing page blank?

The signing page is deny-by-default: it will not load in an iframe until you add your app's origin to your allowed embedding domains. Add the exact https origin and reload.

Start embedding signing today

Create a free account, allow-list your domain, and generate your first single-use signing URL in minutes.