API & Webhook Documentation

0. Authentication (login)

To use the API, first authenticate to obtain an access token (Bearer).

POST /api/login

Expected fields:

  • email (string, required)
  • password (string, required)

Example request

POST /api/login
Content-Type: application/json

{
  "email": "admin@email.com",
  "password": "motdepasse"
}

Example response

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOi..."
}

0.1. Registration (register)

To create a user account via the API.

POST /api/register

Expected fields:

  • name (string, required) : Display name
  • email (string, required) : Email address
  • password (string, required) : Password
  • password_confirmation (string, required) : Password confirmation

Example request

POST /api/register
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john.doe@example.com",
  "password": "password123",
  "password_confirmation": "password123"
}

Example response (success)

{
  "status": "success",
  "message": "User created successfully.",
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOi..."
}

Example response (error)

{
  "status": "error",
  "message": "Validation error",
  "errors": {
    "email": ["The email address is already used."]
  }
}

0.2. Generate a personal API token

To use the API, each user can generate one or more personal API tokens from their account area ("My API tokens" section). These tokens allow access to all protected API routes.

  • Log in to your GesDocs account
  • Go to "My Account" > "Manage my API tokens"
  • Generate a new token and copy it (it will only be displayed once)
  • Use this token in the header Authorization: Bearer <token> of your API requests

Example usage

POST /api/signature-requests
Authorization: Bearer <your_api_token>
Content-Type: multipart/form-data

...

0.3. Get available regions and languages

This endpoint returns the list of available regions (timezones) and languages for use in the API.

GET /api/meta

Example response

{
  "regions": ["Europe/Paris", "Europe/London", ...],
  "languages": [
    {"code": "fr", "label": "Français"},
    {"code": "en", "label": "English"}
  ]
}

1. Create a signature request (API)

Endpoint to create a remote signature request via the REST API.

POST /api/signature-requests

Accepted formats

  • JSON : for sending only URLs (pdf_url, logo_url)
  • multipart/form-data : for sending files (pdf, logo) and/or classic fields

Required fields

  • signers (array, required): List of signers (email, first_name, last_name, language, ...)
  • expires_at (string, required): Expiration date (YYYY-MM-DDTHH:mm:ss)
  • demandeur_email (string, required): Requester email
  • pdf (file, required in multipart) or pdf_url (string, required in JSON)
  • logo (file, optional in multipart) or logo_url (string, optional in JSON)
  • color (string, optional): Main color (hex)
  • metadata (object, optional): Additional data

Example JSON request

POST /api/signature-requests
Authorization: Bearer <token>
Content-Type: application/json

{
  "signers": [
    {
      "email": "alice@email.com",
      "first_name": "Alice",
      "last_name": "Dupont",
      "language": "fr"
    }
  ],
  "expires_at": "2025-12-31T23:59",
  "demandeur_email": "admin@email.com",
  "pdf_url": "https://exemple.com/monfichier.pdf",
  "logo_url": "https://exemple.com/monlogo.png"
}

Example multipart/form-data request

  • signers[0][email] = alice@email.com
  • signers[0][first_name] = Alice
  • signers[0][last_name] = Dupont
  • signers[0][language] = fr
  • expires_at = 2025-12-31T23:59
  • demandeur_email = admin@email.com
  • pdf = (joindre le fichier PDF)
  • logo = (joindre le logo, optionnel)
  • color = #4f46e5 (optionnel)
  • metadata = {"custom_id": "ABC123"} (optionnel)

Notes

  • If you use JSON, you must provide pdf_url (and optionally logo_url).
  • If you use multipart, you must provide pdf (and optionally logo).
  • If you provide both a file and a URL for the same field, the file is prioritized.
  • Validation errors will indicate precisely missing or malformed fields.

Example response (success)

{
  "status": "success",
  "message": "Signature request created successfully",
  "data": {
    "signature_request": {
      "id": 123,
      "email": "john.doe@email.com",
      "signer_first_name": "John",
      "signer_last_name": "Doe",
      "signer_language": "fr",
      "signer_2fa": true,
      "signer_mobile": "0612345678",
      "statut": "en_attente",
      "expires_at": "2025-12-31T23:59:00",
      "requester_email": "admin@email.com",
      "metadata": {"custom_id": "ABC123"},
      "logo_url": "https://.../logos/xxxx.png",
      "color": "#4f46e5",
      "region": "Europe/Paris",
      ...
    },
    "signature_url": "https://.../fr/sign/xxxx?email=...&check=...",
    "credits_left": 42
  }
}

The field credits_left indicates the number of credits left for the authenticated user.

1.1. Mode multi-signataire et gestion des balises

GesDocs prend en charge le mode multi-signataire : vous pouvez définir plusieurs signataires pour un même document, chacun devant signer à des emplacements précis ou communs selon les balises présentes dans le PDF.

  • <@signature@> : chaque signataire doit signer à cet emplacement (balise commune).
  • <@signature1@>, <@signature2@>, etc. : seul le signataire n°N doit signer à cet emplacement (balise individuelle).
  • Si le document ne contient aucune balise, une page récapitulative est ajoutée à la fin du PDF signé, listant toutes les signatures (image, nom, prénom, date/heure).

Le webhook et l'API retournent pour chaque demande :

  • La liste complète des signataires (signataires), avec leur statut et date de signature.
  • Le lien vers le PDF signé et le certificat PDF/JSON.
  • Pour chaque événement, le webhook POSTe l'état de tous les signataires et le détail du document.

Exemple de payload Webhook pour un document multi-signataire :

{
  "event": "document_signed",
  "data": {
    "id": 123,
    "token": "...",
    ...
    "signataires": [
      { "email": "alice@email.com", "prenom": "Alice", "nom": "Dupont", "statut": "signed", "date_signature": "2025-05-04T15:00:00" },
      { "email": "bob@email.com", "prenom": "Bob", "nom": "Martin", "statut": "pending", "date_signature": null }
    ],
    ...
  }
}

Résumé : GesDocs gère nativement les workflows multi-signataires, l'API et le webhook exposent l'état de chaque signataire, et la page récapitulative PDF est générée automatiquement si aucune balise n'est présente dans le document.


2. Webhook (automatic notifications)

You can configure a webhook URL in the "My Account" section. For each event (signature, refusal, etc.), GesDocs will send a POST request with the event details.

Webhook URL: To be set in "My Account" > Webhook URL

Example JSON payload sent:

{
  "event": "document_signed",
  "data": {
    "id": 123,
    "token": "a31e9ec7-b5a3-4b76-bf53-a35062ccff14",
    "document_hash": "...",
    "signataire": {
      "email": "alice@email.com",
      "prenom": "Alice",
      "nom": "Dupont"
    },
    "signataires": [
      {
        "email": "alice@email.com",
        "prenom": "Alice",
        "nom": "Dupont",
        "statut": "signed",
        "date_signature": "2025-05-04T15:00:00"
      },
      {
        "email": "bob@email.com",
        "prenom": "Bob",
        "nom": "Martin",
        "statut": "pending",
        "date_signature": null
      }
    ],
    "statut": "signe",
    "date_creation": "2025-05-04T13:49:56",
    "date_expiration": "2025-05-04T14:49:00",
    "date_signature": "2025-05-04T15:00:00",
    "demandeur": { "email": "admin@email.com" },
    "utilisateur": { "email": "admin@email.com", "entreprise": "Ma société" },
    "document_signe": { "url": "https://.../pdf/signes/xxx.pdf" },
    "certificat_pdf": { "url": "https://.../pdf/certificats/xxx.pdf" },
    "certificat_json": { "url": "https://.../pdf/certificats/xxx.json" },
    "ip": "1.2.3.4",
    "navigateur": "Mozilla/5.0 ...",
    "preuve": { ... },
    "metadata": { ... }
  },
  "credits_left": 42
}

The field credits_left indicates the number of credits left for the user at the time of the event.

The webhook is called via POST, JSON format, for each important status change (signature, refusal, etc.).


2. Verify the authenticity of a signed document (API)

This endpoint allows you to verify the authenticity of a signed PDF document and its certificate PDF generated by GesDocs.

POST /api/verify-document

Expected fields (multipart/form-data)

  • document (file, required) : The signed PDF document to verify
  • certificate (file, required) : The certificate PDF generated by GesDocs

Example request (multipart/form-data)

POST /api/verify-document
Authorization: Bearer <token>
Content-Type: multipart/form-data

document: <signed PDF file>
certificate: <certificate PDF file>

Example response (success)

{
  "valid": true,
  "message": "Signature valid and authentic.",
  "debug": {
    "hash_from_cert": "...",
    "hash_of_doc": "...",
    "uuid_from_cert": "...",
    "date_from_cert": "03/05/2025 20:01:09",
    "date_in_db": "03/05/2025 20:01:09"
  }
}

Example response (failure)

{
  "valid": false,
  "message": "The document hash does not match the certificate hash.",
  "debug": {
    "hash_from_cert": "...",
    "hash_of_doc": "...",
    "uuid_from_cert": "...",
    "date_from_cert": "03/05/2025 20:01:09",
    "date_in_db": "03/05/2025 20:01:09"
  }
}

Secure Download (API)

This endpoint allows you to create a secure download link and notify recipients by email.

POST /api/secure-downloads

Expected fields (JSON or multipart/form-data)

  • files (array of objects, required): List of files to share (path, name). You can provide a file path (uploaded) or a url (remote PDF).
  • signers (array of objects, required): List of recipients (email, first_name, last_name, language, region, mobile if 2FA SMS)
  • demandeur_email (string, required): Requester email
  • expires_at (date, required): Expiration date (YYYY-MM-DD)
  • logo (file, optional): Custom logo (image, shown in emails and download page)
  • logo_url (string, optional): URL of a custom logo image (PNG, JPG, GIF, WEBP). If both logo and logo_url are provided, the uploaded file is used.
  • twofa_type (string, optional): 2FA type (mail or sms, default: mail)

For each file in files[], you can provide either:

  • path: Path to a file uploaded to S3 (from the web interface or presigned URL)
  • url: URL to a remote PDF file (the API will download and store it on S3)

If both path and url are provided, path is used.

Example request (JSON)

{
  "files": [
    { "name": "Document.pdf", "url": "https://example.com/file.pdf" },
    { "name": "Autre.pdf", "path": "secure_downloads/abc123_Autre.pdf" }
  ],
  "signers": [
    { "email": "john@example.com", "first_name": "John", "last_name": "Doe", "language": "en" }
  ],
  "demandeur_email": "alice@example.com",
  "expires_at": "2025-06-01T12:00:00",
  "logo_url": "https://example.com/logo.png"
}

Example request (multipart/form-data)

files[0][name]: Document.pdf
files[0][path]: secure_downloads/abc123_Document.pdf
signers[0][email]: john@example.com
signers[0][first_name]: John
signers[0][last_name]: Doe
demandeur_email: alice@example.com
expires_at: 2025-06-01T12:00:00
logo: (file upload)

Example response (success)

{
  "status": "success",
  "message": "Link sent to recipients.",
  "data": {
    "secure_download_id": 123,
    "token": "...",
    "expires_at": "2025-06-01T12:00:00",
    "link": "https://gesdocs.fr/secure-downloads/123"
  }
}

Example response (error)

{
  "status": "error",
  "message": "Unable to download the file from the provided URL.",
  "field": "files.0.url"
}
{
  "status": "error",
  "message": "The file at the provided URL is not a valid PDF.",
  "field": "files.0.url"
}
{
  "status": "error",
  "message": "Unable to download the logo from the provided URL.",
  "field": "logo_url"
}
{
  "status": "error",
  "message": "The file at the provided URL is not a valid image.",
  "field": "logo_url"
}

If you provide a remote file or logo URL, the API will attempt to download and store it. If the file is not accessible or not valid, an error will be returned.