e-Signature.eu REST API — electronic registered mail

1. Overview

The e-Signature.eu REST API lets your application send electronic registered mail without using our website. You send the PDF, a verified sender address and the recipient; the document receives a qualified electronic timestamp, and the recipient signs an acknowledgement of receipt after verifying his identity. You get the result back through the API or a callback.

Base URL https://api.e-signature.eu/v3/regis/
Postman Postman documentation and collection

The previous base URL https://www.e-signature.eu/wp-json/esig/v3/regis/ remains valid. We recommend using the api.e-signature.eu URL.

2. Authentication

Your credentials are available in My account > Signatures API once you are logged in on e-signature.eu:

  • User ID: sent in the URL as the userid parameter of every call;
  • API token: sent in the x-api-key HTTP header of every call.
curl -X GET "https://api.e-signature.eu/v3/regis/requestBalance?userid=123" \
  -H "x-api-key: YOUR_API_TOKEN"

Keep your token secret: it gives full access to your account through the API. Calls must be made from your server, never from a browser or a mobile app.

3. Conventions

Requests and responses

  • HTTPS only. Request bodies are JSON (Content-Type: application/json).
  • Every response is JSON, in one of these two forms:
{ "success": true,  "result": { ... } }
{ "success": false, "error": "Readable error message" }

Limits

Limit Value
Requests 10 per minute per account and IP address (HTTP 403 beyond, retry after one minute)
Document One PDF per request, 30 MB maximum, not encrypted / not password protected
Download of signed documents 30 days after completion (see Retention)

4. Credits

Requests are paid with your prepaid e-signature.eu credits. The price of a method can be retrieved with getMethods (it takes your specific prices into account). Your balance is returned by requestBalance and in every request object (credits_balance).

Automatic credit recharge

To avoid running out of credits, you can let your account recharge itself automatically. It is set up once in My account > Signatures API, not through the API:

  1. Choose a threshold (in credits) and the credit pack to order.
  2. Save a payment method with our payment provider Mollie (card, or SEPA Direct Debit through Bancontact, iDEAL…). A verification payment of €0.01 is requested once.
  3. Whenever credits are debited and your balance falls below the threshold, an order for the chosen pack is created and paid automatically with the saved payment method. The invoice is sent to you by email.
Automatic recharge
Trigger A debit of credits (e.g. a new request) that brings the balance below the threshold
Credits added As soon as the payment is confirmed: immediately by card, after a few working days by SEPA Direct Debit
Recharges in progress One at a time
Safety limit A maximum number of automatic recharges per 30 days
Payment failure The order is marked as failed, automatic recharge is turned off and you are informed by email
The recharge is triggered by a debit. A request that costs more than your current balance is refused (HTTP 403, You do not have enough credits) and does not trigger a recharge: choose a threshold higher than the cost of your largest requests, and keep a margin when paying by SEPA Direct Debit. Your balance remains available at any time through requestBalance and credits_balance.

5. How a registered mail works

  1. You send the PDF, a verified sender address and the recipient. The document receives a qualified electronic timestamp and the credits are debited.
  2. The recipient receives an email with two links: one to sign the acknowledgement of receipt and access the document, one to decline.
  3. To sign, the recipient verifies his identity with one of the accepted methods (itsme®, Evrotrust, OTP…).
  4. The registered mail becomes finished (signed), declined, or expired if nothing happened after 14 days.

One sender, one recipient per registered mail. As on the website, an automatic reminder is sent every 4 days (not configurable); there is no manual reminder and no cancellation.

6. Sender address

As on the website, the sender address (sender_email) must be verified before it can be used:

  1. Call verifySender: an email with a verification link is sent to the address (response 202). If the address is already verified, the response is 200 with "verified": true.
  2. The owner of the address clicks the link.
  3. The address can then be used in request.
POST/v3/regis/verifySender?userid={userid}
{ "email": "[email protected]", "lang": "en" }
{
  "success": true,
  "result": {
    "email": "[email protected]",
    "verified": false,
    "message": "A verification email has been sent to [email protected]. The address can be used as sender_email once the link in this email has been clicked."
  }
}
GET/v3/regis/senders?userid={userid}

Lists the sender addresses of your account with their status.

{
  "success": true,
  "result": [
    {
      "email": "[email protected]",
      "verified": true
    },
    {
      "email": "[email protected]",
      "verified": false
    }
  ]
}

7. Send a registered mail

POST/v3/regis/request?userid={userid}
{
  "title": "Formal notice rent October",
  "lang": "en",
  "sender_email": "[email protected]",
  "recipient": {
    "firstname": "Ann",
    "lastname": "Peeters",
    "email": "[email protected]",
    "phone": "+32475111222"
  },
  "methods": [
    "itsme-qes-signature",
    "evrotrust-signature"
  ],
  "send_email": true,
  "note_html": "Please acknowledge receipt.",
  "signature_redirect": "https://www.example.com/thank-you",
  "external_reference": "INV-2026-0042",
  "metadata": {
    "customer_id": 311
  },
  "pdf_file_base64": "JVBERi0xLjcKJeLjz9MK..."
}
Field Required Type Description
title yes string Name of the document. Letters, digits and dashes are kept; a suffix -1, -2… is added if the name already exists.
lang yes string Language of the emails and pages: fr, nl, en, de, es.
sender_email yes string Verified sender address, see Sender address.
recipient.lastname, recipient.email yes string
recipient.firstname no string
recipient.phone no string International format (+32…). An invalid number is ignored.
methods yes array Methods accepted to sign the acknowledgement of receipt, see getMethods.
pdf_file_base64 yes string The PDF, base64 encoded. One file, 30 MB maximum, not encrypted.
send_email no boolean Default true. With false, no email is sent to the recipient nor to the sender: send the signature_link and declined_link yourself.
note_html no string Message added to the email sent to the recipient.
signature_redirect no string (URL) Page shown to the recipient after signing.
external_reference no string Your own identifier (invoice, file…), max 255 characters.
metadata no object Free JSON object, max 4 KB, returned as is.
callback_url no string (URL) Callback URL for this registered mail only (public HTTPS). Default: the URL of your account.

Cost

Price of the most expensive method in methods, for one recipient. Debited when the registered mail is created.

Response 201 Created

{
  "success": true,
  "result": {
    "type": "regis",
    "id_sign": 123,
    "doc_name": "Formal-notice-rent-October",
    "lang": "en",
    "sender_email": "[email protected]",
    "status_id": "pending",
    "date_added": "2026-10-20 11:50:00",
    "date_status": "2026-10-20 11:50:00",
    "date_expired": "2026-11-03 11:50:00",
    "timezone": "Europe/Brussels",
    "methods": [
      "itsme-qes-signature",
      "evrotrust-signature"
    ],
    "reminder": 4,
    "last_reminder": null,
    "send_email": true,
    "from_api": true,
    "credits": 1,
    "credits_balance": 41,
    "recipient": {
      "firstname": "Ann",
      "lastname": "Peeters",
      "email": "[email protected]",
      "phone": "+32475111222",
      "status": "pending",
      "signing_time": "",
      "signing_method": "",
      "verified_firstname": "",
      "verified_lastname": "",
      "signature_link": "https://www.e-signature.eu/en/sign-regis/?key=…",
      "declined_link": "https://www.e-signature.eu/en/sign-regis/?key=…"
    },
    "external_reference": "INV-2026-0042",
    "metadata": {
      "customer_id": 311
    }
  }
}

8. The registered mail object

Returned by request, getRequest, modifyRecipient, delete and sent in the callbacks. The field "type": "regis" distinguishes it from a signature request when both use the same callback URL.

Field Description
id_sign Identifier of the registered mail
status_id pending waiting for the recipient · finished acknowledgement signed · declined declined by the recipient · expired not signed after 14 days · deleted
date_added, date_status, date_expired Creation, last status change, expiry (time zone of the registered mail)
sender_email, lang, methods, reminder, send_email As defined at creation
last_reminder Date of the last reminder, or null
credits, credits_balance Credits of the registered mail, current balance of your account
recipient firstname, lastname, email, phone, status; once signed signing_time, signing_method, verified_firstname, verified_lastname; while pending signature_link and declined_link
pdf_file_base64 Timestamped document, once the registered mail is no longer pending
receipt_file_base64 Signed acknowledgement of receipt, when finished
external_reference, metadata As sent at creation

9. Other endpoints

All endpoints take userid in the URL and x-api-key in the headers. id_sign is passed in the URL.

List the registered mails

GET/v3/regis/list?userid={userid}&status_id=pending

status_id (optional): pending, finished, declined or expired. external_reference (optional): only the registered mails with this reference.

{
  "success": true,
  "result": [
    {
      "id_sign": 123,
      "status_id": "pending",
      "doc_name": "Formal-notice-rent-October",
      "date_added": "2026-10-20 11:50:00",
      "external_reference": "INV-2026-0042"
    }
  ]
}

Get a registered mail

GET/v3/regis/getRequest?userid={userid}&id_sign=123

Modify the recipient

PATCH/v3/regis/modifyRecipient?userid={userid}&id_sign=123
{ "email": "[email protected]", "phone": "+32475333444" }

Registered mail pending only. Send only the fields to change among firstname, lastname, email, phone. If the email changes, the previous recipient is informed that the registered mail is cancelled for him and the new recipient receives it.

Delete a registered mail

DELETE/v3/regis/delete?userid={userid}&id_sign=123

Status finished, declined or expired only. Deletes the files and the history; the response contains the registered mail one last time (status_id: deleted): download the documents before deleting.

Download the audit trail

GET/v3/regis/requestAuditTrail?userid={userid}&id_sign=123

Not available while pending. Returns the registered mail with audit_trail_base64: a timestamped PDF with the full history.

Get the credit balance

GET/v3/regis/requestBalance?userid={userid}

List the methods

GET/v3/regis/getMethods?userid={userid}&lang=en

Methods accepted in methods for registered mail, with the price for your account. The list can differ from the one of the signatures API.

{
  "success": true,
  "result": [
    {
      "id": "itsme-qes-signature",
      "label": "itsme® | QES",
      "credits": 1
    },
    {
      "id": "otp-email-non-qualified",
      "label": "OTP by Email/SMS | SES",
      "credits": 0.4
    }
  ]
}

10. Callbacks (webhooks)

Define your callback URL in My account > Signatures API (HTTPS, publicly reachable). You can also set a callback_url per request. The callback is a POST with a JSON body containing the full current state of the request (same format as getRequest), sent for requests created through the API.

Event fields

Field Description
event Event type (see below)
event_id Unique identifier of the event (evt_…). Identical on every retry of the same event: use it to ignore duplicates.
event_at Date of the event (UTC, ISO 8601)
changes Recipient status change, e.g. [{"signer_key": 1, "from": "pending", "to": "signed"}] (only when a signer changed)
changes (signer.email_failed) Undelivered email, e.g. [{"signer_key": 2, "email": "[email protected]", "bounce_type": "permanent", "reason": "smtp; 550 5.1.1 user unknown"}]
external_reference, metadata As sent when the request was created

Event types

Event When
signer.signed A signer signed, the request is still in progress
signer.declined, signer.skipped, signer.expired A signer declined, was skipped or expired
request.completed All signers signed: the signed PDF is included (pdf_file_base64)
request.stopped The request was stopped: the partially signed PDF is included
request.cancelled The request was cancelled
request.deleted The request was deleted
request.expired The request expired
request.declined Registered mail declined by the recipient
signer.email_failed An email sent to a signer could not be delivered, see Undelivered emails
request.updated Any other change: reminder sent, signer modified, new signing links…

The body always contains the full current state: your integration can rely on status_id and on the status of each signer rather than on the event type alone.

Undelivered emails

When an email sent by e-Signature.eu to a signer (or to the recipient of a registered mail) is returned by his mail server (unknown address, mailbox full, server refusing the message…), you receive the callback signer.email_failed. The status of the request and of the signer does not change.

Field of changes Description
signer_key Key of the signer in signers (always 1 for a registered mail)
email Address in error
bounce_type permanent: the address does not exist or refuses messages · transient: temporary problem (mailbox full, server unavailable), delivery abandoned after several attempts · undetermined: unknown reason
reason Technical message of the recipient’s mail server, when available

Correct the address with modifySigner (signature request) or modifyRecipient (registered mail): the invitation is sent to the new address, and no cancellation email is sent to the address in error. The account owner is also informed by email, and the signer is marked Email not delivered in the online dashboard.

permanent: no more emails are sent to this address for this request (reminders included) until it is corrected. transient or undetermined: emails are not blocked; the next reminder is sent normally and, if it fails again, you receive a new signer.email_failed callback.

Only pending requests and signers who have not signed yet are concerned. With send_email: false, e-Signature.eu sends no email to the signers, so this event does not occur.

Headers

Header Example
X-Esig-Api-Version 3
X-Esig-Event signer.signed
X-Esig-Event-Id evt_4f0c2b9e1d7a3c55e8b1a2f0
X-Esig-Delivery-Attempt 1, 2, …
X-Esig-Signature t=1792407600,v1=5d41402abc4b2a76b9719d911017c592…

Verifying the signature

Your signing secret is shown in My account > Signatures API, where it can also be regenerated. v1 is the HMAC-SHA256 of "<t>.<raw request body>" with your secret, hex encoded. Use the raw body, before any JSON parsing, and reject callbacks older than 5 minutes.

PHP

$body   = file_get_contents( 'php://input' );
$header = $_SERVER['HTTP_X_ESIG_SIGNATURE'] ?? '';
preg_match( '/t=(\d+),v1=([a-f0-9]{64})/', $header, $m );
$valid = $m
    && abs( time() - (int) $m[1] ) <= 300
    && hash_equals( hash_hmac( 'sha256', $m[1] . '.' . $body, $secret ), $m[2] );

Node.js

const crypto = require('crypto');
function verify(rawBody, header, secret) {
  const m = /t=(\d+),v1=([a-f0-9]{64})/.exec(header || '');
  if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
  const expected = crypto.createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]));
}

C# (.NET)

using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions;
static bool Verify(string rawBody, string header, string secret) {
    var m = Regex.Match(header ?? "", @"t=(\d+),v1=([a-f0-9]{64})");
    if (!m.Success || Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - long.Parse(m.Groups[1].Value)) > 300) return false;
    using var h = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
    var expected = Convert.ToHexString(h.ComputeHash(Encoding.UTF8.GetBytes(m.Groups[1].Value + "." + rawBody))).ToLowerInvariant();
    return CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(expected), Encoding.ASCII.GetBytes(m.Groups[2].Value));
}

Responses and retries

  • Reply with HTTP 2xx as soon as the callback is received, and process it asynchronously if needed.
  • On network error, timeout (30 s), HTTP 429 or 5xx, the callback is sent again every hour with the same event_id, up to 24 attempts. Other 4xx answers are considered final. If the request changes again before a successful delivery, the next callback carries a new event and the full current state. The current state remains available at any time through getRequest.
  • Redirects are followed (the POST method is kept). localhost and private addresses can not be used.

For registered mail, the callback is sent when the acknowledgement is signed, declined or expired, at each automatic reminder and when the recipient is modified (on the website or through the API). The recipient is signer_key 1 in changes.

11. Errors

Errors are returned with "success": false and a readable error message. Rely on the HTTP code for your logic: messages may be improved over time.

HTTP code Meaning
200 / 201 / 202 OK / registered mail created / verification email sent
400 Missing or invalid field (the message names the field)
401 Invalid userid or x-api-key
403 Not enough credits, or request limit reached (10 per minute)
404 Missing id_sign, or unknown for this account
412 Action not possible in the current state (sender address not verified, wrong status)

12. Retention

The timestamped document and the signed acknowledgement of receipt can be downloaded for 30 days, through getRequest or the callback. The audit trail is kept for the period defined in our DPA. Archive the documents on your side within 30 days.

Shopping cart

0
image/svg+xml

No products in the cart.

Continue Shopping