Embedded signing
Load the signing screen inside your own product: an allow-list of origins, an embed session per signer, and postMessage events back to your page.
Why an allow-list
frame-ancestors for exactly one origin per request.1. Allow-list your origins
Scheme and host, optionally a port. No paths, no wildcards. Growth plan or above.
# Developer → Embedded signing in the dashboard, or:
curl -s -X PUT "$BASE/embedded-signing" \
-H "Authorization: Bearer $QUATHOS_SIGN_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "allowed_origins": ["https://app.example.com"] }'2. Issue an embed session
From your backend, for the participant whose turn it is. The URL is the signer’s personal link with your origin attached — treat it as a credential: never log it, never put it in a long-lived page.
curl -s -X POST "$BASE/envelopes/6b1d.../participants/9f2a.../embed-session" \
-H "Authorization: Bearer $QUATHOS_SIGN_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "origin": "https://app.example.com" }'
# → { "url": "https://sign.quathos.com/sign/<token>?embed=https%3A%2F%2Fapp.example.com",
# "origin": "https://app.example.com", "expires_at": "2026-10-10T12:00:00Z" }It replaces the emailed link
signing-link, issuing an embed session invalidates the link that was emailed to the signer. If you embed, do not also expect the email link to work.3. Render the iframe and listen
Check event.origin against the Quathos Sign origin and event.data.source against "quathos-sign". Events: ready, signed, declined, delegated. Treat them as UI hints; the source of truth is the webhook (participant.signed, envelope.completed).
<iframe
src="{url}"
title="Sign the agreement"
allow="camera"
style="width:100%;height:80vh;border:0"
></iframe>
<script>
window.addEventListener('message', (event) => {
if (event.origin !== 'https://sign.quathos.com') return;
if (event.data?.source !== 'quathos-sign') return;
switch (event.data.event) {
case 'ready': /* iframe loaded */ break;
case 'signed': /* close, refresh your record; the webhook will confirm */ break;
case 'declined': break;
case 'delegated': break;
}
});
</script>What does not change
- The signer still goes through every step: one-time code, identity check if you asked for one, consent, signature. Embedding changes the frame, not the proof.
- The evidence report and dossier are identical to a non-embedded signature.
- If the page loads outside an allow-listed origin, the screen shows as a full page and sends no events.