Documentation menu

Signing inside your product

The person is already in your app. Do not send them to their inbox.

Three ways to put signing in front of somebody, from least work to most:

  • Send them to our page. The url in the send's answer, in a new tab or as a redirect; set return_url on the document and the signed page offers the way back.
  • Frame our page on your own site. This page.
  • Build your own page on the signing routes (/v1/sign/{token}), which take no key and answer a browser on any site. The Node client's SignSealerSigning is that client.

1. Send without sending

Give the signer delivery: "embedded". Nothing is emailed or texted to them, and the automatic reminders leave them alone: you are showing them the page yourself. They still need an email address or a mobile number, because the certificate records how they could be reached and the completed copy goes to them.

const { links } = await signsealer.send(documentId, [
  { email: "dana@example.com", full_name: "Dana Reyes", delivery: "embedded" },
]);

2. A fresh link when the page is shown

Do not keep the link from the send in your database: it is a bearer credential. Mint one when the person opens the screen that shows it. The link they had stops working, and the trail records that one was shown.

const { url, frame_origins } = await signsealer.embedLink(documentId, signerId);
// POST /v1/documents/{id}/signers/{signer}/embed

3. Put it in a frame, on a site the business has proven

The signing page may be framed only on sites the business has proven are its own, and the browser enforces it (frame-ancestors): anywhere else the frame stays empty. A business proves a site in one of three ways, the same three that let a signed page send somebody back to it:

  • a signing domain it verified (Settings, under Your own domains), and every host under it;
  • a company sign-in domain it proved (Settings → Single sign-on), and every host under it;
  • the site of an app it connected, such as a WordPress site running our plugin: that one host.

frame_origins on the embed answer, and on GET /v1/account, lists them. Empty means nowhere yet. The business's public forms (/f/{business}/{form}) may be framed on the same sites.

<iframe src="{url}" title="Sign your rental agreement"
        style="width:100%;border:0;min-height:640px"
        allow="camera; geolocation"></iframe>

allow="camera" lets a template that asks for a photograph use it; geolocation, one that asks where the signer is.

4. Hear what happened

Inside a frame the page posts a message to the page around it:

{ source: "signsealer", event, document_id, signer_id, height }
eventWhen
readyEvery page, as it loads.
resizeThe page's height changed: set the frame's height to height and there is no inner scrollbar.
signedThey have signed. Other signers may still be to come; signing.completed on your webhook is when everyone has.
declinedThey declined.
window.addEventListener("message", (e) => {
  if (e.origin !== new URL(url).origin) return;      // only the signing page
  const m = e.data;
  if (!m || m.source !== "signsealer") return;
  if (m.event === "resize" || m.event === "ready") frame.style.height = m.height + "px";
  if (m.event === "signed") showThanks();
  if (m.event === "declined") showDeclined();
});

Treat the message as a hint to update the screen, not as proof: anything that matters — releasing an order, unlocking a booking — waits for the webhook, which is signed, or for GET /v1/documents/{id}.

What the page does and does not do in a frame

  • It sets no cookie, so a browser that blocks third-party cookies changes nothing.
  • It carries one script in a frame, pinned by its hash in the page's own policy, and none at all when opened in a tab. The message is the only thing it does.
  • The way back on the signed page (return_url) leaves the frame for the whole window.
  • A frame on a site that is not proven shows nothing, and that is the browser refusing on our instruction, not an error to work around.

Ready to build? An API key takes a minute in the portal, and the free plan covers the first 25 agreements a month.

Get an API key