SignEnvoy docs
Sign in Start in the sandbox

Guides

Recipient authentication

Every recipient is verified at least by their signing link. A sender can ask for more: a one-time code emailed to the recipient's same address, which the recipient enters before the envelope is shown. The level that was satisfied is recorded in the envelope's audit trail and printed on the certificate page, so higher assurance is provable, not only enforced.

The levels

auth_levelWhat it meansStatus
linkThe signing link is the credential, whether SignEnvoy emailed it or you delivered it. The default.Available
otpThe signing link, plus a 6-digit code emailed to the same address. The envelope is not shown until the code is entered.Available

These are the two levels. A request naming any other value is refused as invalid; there is no account-based level, because signers have no accounts: the signing link, optionally with a one-time code, is the credential.

Setting the level

In the API

auth_level is a property of each recipient, accepted wherever recipients are given: POST /v1/documents, PUT /v1/documents/{id}/recipients, POST /v1/templates (placeholder roles), POST /v1/templates/{id}/use, and each row's recipients in POST /v1/bulk-sends.

curl -s -X POST https://app-staging.signenvoy.com/v1/documents \
  -H "Authorization: Bearer $SENV_API_KEY" \
  -F 'document={
    "title": "Lease",
    "recipients": [
      {"name": "Ada Lovelace", "email": "ada@example.com", "auth_level": "otp"},
      {"name": "Bob Byrne", "email": "bob@example.com"}
    ]
  };type=application/json' \
  -F file=@lease.pdf

Ada must enter a code before she sees the envelope; Bob's link alone is his credential. Omitting auth_level means link.

Not with delivery: "none"

otp needs SignEnvoy to deliver the links. Sending an envelope with delivery: "none" while any recipient has auth_level: "otp" answers 422 validation-failed, and so does reassigning a recipient of such an envelope to otp: when you deliver the links yourself, you authenticate the signer. SignEnvoy never emails a one-time code for an envelope it does not deliver. Recipients are accepted with otp at every call above; the check is made when the envelope is sent, where the delivery is chosen.

In the dashboard

On the Recipients step of the send flow, open More options and choose, per person, between "Signing link only" and "Signing link plus a one-time code". The review step and the envelope page show the level next to each recipient, and a badge reads "Verified by a one-time code" once it has been satisfied.

What the recipient experiences

  1. The first screen explains itself before asking for anything: who is asking, why this envelope needs a code, and the masked address the code goes to (for example a***@example.com). Declining the request is possible from this screen; a recipient is never forced through the code to say no.
  2. The recipient sends the code to their address. The email comes from your sender name, like the invitation, and is plain text. Each code is six digits and works for 10 minutes. Only the most recent code counts.
  3. A wrong code says so and shows the attempts left. After 5 wrong attempts the link stops working; the sender can re-send, which issues a fresh link that starts with a clean count.
  4. A new code can be requested after a 60 second cooldown, at most 10 times in 24 hours. The waiting screen counts the seconds down.
  5. "Request a new link" stays reachable at every step, so a recipient whose code expired or whose attempts ran out is never stranded.
  6. Once the code is accepted, the consent screen and the envelope appear as they would for any other recipient.

What integrators see on the ceremony API

If you drive the signing surface yourself, the session object carries an auth member:

{
  "auth": {
    "required": true,
    "level": "otp",
    "satisfied": false,
    "destination_masked": "a***@example.com",
    "resend_after_s": 0
  },
  "recipient": { "email": "a***@example.com", ... },
  "fields": []
}

While required is true and satisfied is false, the recipient's email is masked, fields is empty, and the PDF, consent, field, and completion routes answer auth-required (409). Two routes move the session forward:

  • POST /ceremony/v1/session/{token}/otp/send: emails a code; returns resend_after_s and destination_masked. Inside the cooldown or past the daily limit it answers rate-limited with Retry-After.
  • POST /ceremony/v1/session/{token}/otp/verify with {"code": "123456"}: 204 on success, after which the session reloads with satisfied: true and the fields present.

Verification can fail three ways:

  • otp-invalid (422): wrong code; the body carries attempts_remaining.
  • otp-expired (410): the code is older than 10 minutes; request a new one.
  • otp-attempts-exhausted (403): 5 wrong codes; this link is done. The sender's re-send issues a fresh link.

Rejecting the request (POST .../reject) works before the code is entered.

Test mode

For an envelope created with a test key the code is emailed only when the recipient is a member of your workspace. It is always stored with the captured emails and shown in the dashboard under Settings, Test mode, as "Code sent to {email}: {code}", so you can walk the whole flow without a mailbox.

What the record says

The satisfied level is an audit event on the envelope. For each signer the certificate page first says how the link they used was delivered:

  • "Signing link emailed to this address by SignEnvoy"
  • "Signing link delivered by the sender" (you returned it from the API or an embed session)

then a "Verified by:" line with one of two sentences:

  • "Signing link"
  • "Signing link plus a one-time code emailed to this address"

The recipient's completion screen says the same thing in the second person ("You were verified by your signing link.", or "You were verified by the signing link plus a one-time code emailed to this address."), so what the recipient read and what the artifact records never differ.