Skip to content

Embedded signing

Let people sign inside your own app or on your device: create a one-off signing URL for the recipient whose turn it is.

On this page

When to use it

  • In your app: the person is already logged in to your product, and you want them to sign right there instead of waiting for an email.
  • In person: a customer signs on a tablet at your desk or counter. Add them with the role in_person_signer — they get no emails, so a signing URL is the only way in.

The flow

  1. Create and send the envelope as usual, with the recipient on it.
  2. When it’s their turn, your server asks Signkoi for a signing URL.
  3. You open that URL for the person; they sign on Signkoi’s signing page.
  4. A webhook (or a status check) tells your server they finished.

Create a signing URL

Call POST/v1/envelopes/{id}/recipients/{rid}/signing-url from your server, right before you need it.

curl -X POST https://signkoi.com/api/v1/envelopes/9b2f4c1e-7a3d-4e8b-9c51-2d6f8a0b3e47/recipients/c4e1a8f2-3b7d-4f19-a6c2-8e5d0b9f1a73/signing-url \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"
200 · application/json
{
  "object": "signing_url",
  "url": "https://signkoi.com/s/8kQ2…",
  "recipient_id": "c4e1a8f2-3b7d-4f19-a6c2-8e5d0b9f1a73"
}
Signing URL errors
StatusCodeMeaning
409not_recipients_turnSomeone earlier in the routing order hasn’t finished, or this recipient already has.
409envelope_not_sentThe envelope is a draft, finished or expired.
404resource_missingNo such envelope or recipient.

Open the signing page

Redirect the browser to the URL, open it in a new tab, or load it in an in-app browser or web view on mobile. The signing page runs on signkoi.com and works on any screen size.

Example: redirect from your server
// Your server: an authenticated route in your app, e.g. POST /contracts/:id/sign
app.post('/contracts/:id/sign', requireLogin, async (req, res) => {
    const contract = await db.contracts.find(req.params.id, { owner: req.user.id });

    const r = await fetch(
        `https://signkoi.com/api/v1/envelopes/${contract.envelopeId}/recipients/${contract.recipientId}/signing-url`,
        { method: 'POST', headers: { Authorization: `Bearer ${process.env.SIGNKOI_API_KEY}` } },
    );
    const body = await r.json();
    if (!r.ok) return res.status(409).json({ code: body.error.code });

    // Send the browser straight to the signing page; never store or log the URL.
    res.redirect(303, body.url);
});

No iframes

For security, the signing page can’t be shown inside an iframe on another site (it sends X-Frame-Options: SAMEORIGIN). Use a redirect, a new tab or a web view.

After signing

The recipient sees Signkoi’s confirmation page. Subscribe to recipient.completed and envelope.completed webhooks to update your app, or check the recipient’s status with GET/v1/envelopes/{id}. When the next recipient is also in front of you (for example two in-person signers), request a new URL for them once the first has finished.

Security

  • Anyone with the URL can sign as that recipient. Create it only for an authenticated user who is that recipient.
  • Request a fresh URL every time; don’t store, log, email or share it.
  • Every signing URL you create is recorded in the envelope’s audit trail.
  • Verification still applies: a recipient with an access code or SMS/email code must enter it on the signing page.