Embedded Signing

Let signers complete eSign inside your own application — in an iframe or a popup — and learn when they have finished.

Overview

Every signer in an eSign request gets an eSignLink in the API response. You can send it to the signer (SignCare does this by email/SMS), or open it from your own application so the signer never leaves it. There are two ways to do the latter:

IframePopup
Signer stays on your pageYes, inlineYes, in a separate window
Completion signal in the browserpostMessage event, or your returnUrlyour returnUrl page
Browser permissions to delegatecamera, geolocation (see below)none
MethodsVirtual Sign, Aadhaar eSign, Aadhaar Face. DSC: see Limitationsall

Whichever you choose, the webhook (responseUrl) and the status API are the source of truth for the outcome. Browser events tell you when to refresh your UI, not whether a signature is valid.

Iframe

Load the signer's eSignLink in an iframe and delegate the browser features the signing page may use:

<iframe
  src="{eSignLink}"
  allow="camera; geolocation"
  style="width: 100%; height: 720px; border: 0"
></iframe>
  • camera and geolocation are needed when the request enables photo capture or location for the signer. Without them the signer sees a message that access is blocked and cannot continue.
  • Your page must be served over https.
  • The signer verifies with the OTP sent to them, inside the frame, exactly as on a normal signing link.

Knowing when the signer has finished

Without returnUrl, SignCare's end page sends a message to your page:

{
  type: 'signcare.esign',
  event: 'signed' | 'approved' | 'rejected' | 'failed' | 'expired',
  signerId?: string,
  message?: string   // short reason, for 'failed'
}
window.addEventListener('message', (e) => {
  // Accept messages only from SignCare.
  if (e.origin !== 'https://app.signcare.io') return; // Stage: https://stage.signcare.io
  if (e.data?.type !== 'signcare.esign') return;

  if (e.data.event === 'expired') {
    // The signing session ran out; offer to reload the eSignLink.
  }
  // For every event: refresh your view from your server, which has the webhook result.
});
EventMeaning
signedThe signer completed their signature
approved / rejectedThe document was approved or rejected on the signing page
failedSigning failed, e.g. an Aadhaar OTP or detail mismatch. message carries a short reason.
expiredThe signing session expired inside the frame; reload the eSignLink to continue

The message never contains personal data or the signed document.

With returnUrl, the iframe navigates to your returnUrl after the signer's step, as it does outside an iframe. That page is yours, so it can notify its parent itself:

// on your returnUrl page, loaded inside the iframe
window.parent.postMessage({ type: 'my-app:esign-done' }, window.location.origin);

Open the eSignLink from a user action (a click handler), otherwise browsers block the popup:

const popup = window.open(eSignLink, 'signcare_esign', 'width=1000,height=800');

After signing, the popup navigates to your returnUrl, which can call window.opener.postMessage(...) and window.close(). Also watch for the signer closing the popup early:

const timer = setInterval(() => {
  if (popup.closed) { clearInterval(timer); refreshStatusFromServer(); }
}, 1000);

Limitations

  • DSC (USB token) signing in an iframe needs the SignCare Utility on the signer's machine. Recent Chrome versions also ask the signer to allow access to local devices for the embedding site, and the iframe needs local-network-access in its allow attribute. If that is not an option for your users, use the popup for DSC signers.
  • returnUrl is per signer. It fires after each signer's own step, not when the whole document is complete. Use the webhook for document completion.
  • The signing pages are the only SignCare pages that can be embedded. Other SignCare pages (login, dashboard) refuse to load inside an iframe.

Next

  • Webhooks — the authoritative eSign outcome
  • Environments — Stage vs Live hosts for the eSignLink and the postMessage origin check