Documentation API & Webhook

0. Authentification (login)

Pour utiliser l'API, authentifiez-vous d'abord pour obtenir un jeton d'accès (Bearer).

POST /api/login

Champs attendus :

  • email (chaîne, requis)
  • password (chaîne, requis)

Exemple de requête

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

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

Exemple de réponse

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

0.1. Inscription (register)

Pour créer un compte utilisateur via l'API.

POST /api/register

Champs attendus :

  • name (chaîne, requis) : Nom d'affichage
  • email (chaîne, requis) : Adresse email
  • password (chaîne, requis) : Mot de passe
  • password_confirmation (chaîne, requis) : Confirmation du mot de passe

Exemple de requête

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

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

Exemple de réponse (succès)

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

Exemple de réponse (erreur)

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

0.2. Générer un token API personnel

Pour utiliser l'API, chaque utilisateur peut générer un ou plusieurs tokens API personnels depuis son espace compte (section "Mes tokens API"). Ces tokens permettent d'accéder à toutes les routes protégées de l'API.

  • Connectez-vous à votre compte GesDocs
  • Allez dans "Mon compte" > "Gérer mes tokens API"
  • Générez un nouveau token et copiez-le (il ne sera affiché qu'une seule fois)
  • Utilisez ce token dans l'en-tête Authorization: Bearer <token> de vos requêtes API

Exemple d'utilisation

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

Exemple de réponse

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

1. Créer une demande de signature (API)

Endpoint pour créer une demande de signature à distance via l'API REST.

POST /api/signature-requests

Formats acceptés

  • JSON : pour envoyer uniquement des URLs (pdf_url, logo_url)
  • multipart/form-data : pour envoyer des fichiers (pdf, logo) et/ou des champs classiques

Champs requis

  • 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): Email du demandeur
  • pdf (file, required in multipart) ou pdf_url (string, required in JSON)
  • logo (file, optional in multipart) ou logo_url (string, optional in JSON)
  • color (string, optional): Couleur principale (hexadécimal)
  • metadata (object, optional): Données additionnelles

Exemple de requête JSON

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"
}

Exemple de requête multipart/form-data

  • 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

  • Si vous utilisez JSON, vous devez fournir pdf_url (et éventuellement logo_url).
  • Si vous utilisez multipart, vous devez fournir pdf (et éventuellement logo).
  • Si vous fournissez à la fois un fichier et une URL pour le même champ, le fichier est prioritaire.
  • Les erreurs de validation indiqueront précisément les champs manquants ou mal formés.

Exemple de réponse (succès)

{
  "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
  }
}

Le champ credits_left indique le nombre de crédits restants pour l'utilisateur authentifié.

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 (notifications automatiques)

Vous pouvez configurer une URL de webhook dans la section "Mon compte". Pour chaque événement (signature, refus, etc.), GesDocs enverra une requête POST avec les détails de l'événement.

URL du webhook: À définir dans "Mon compte" > URL du webhook

Exemple de payload JSON envoyé :

{
  "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
}

Le champ credits_left indique le nombre de crédits restants pour l'utilisateur au moment de l'événement.

Le webhook est appelé en POST, format JSON, à chaque changement de statut important (signature, refus, 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) : Le document PDF signé à vérifier
  • certificate (file, required) : Le certificat PDF généré par GesDocs

Exemple de requête (multipart/form-data)

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

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

Exemple de réponse (succès)

{
  "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"
  }
}

Téléchargement sécurisé (API)

Ce endpoint permet de créer un lien de téléchargement sécurisé et de notifier les destinataires par email.

POST /api/secure-downloads

Champs attendus (JSON ou multipart/form-data)

  • files (tableau d'objets, requis): Liste des fichiers à partager (path, name). Vous pouvez fournir un chemin de fichier (uploadé) ou une url (PDF distant).
  • signers (tableau d'objets, requis): Liste des destinataires (email, first_name, last_name, language, region, mobile si 2FA SMS)
  • demandeur_email (chaîne, requis): Email du demandeur
  • expires_at (date, requis): Date d'expiration (YYYY-MM-DD)
  • logo (fichier, optionnel): Logo personnalisé (image, affiché dans les mails et la page de téléchargement)
  • logo_url (chaîne, optionnel): URL d'un logo personnalisé (PNG, JPG, GIF, WEBP). Si logo et logo_url sont fournis, le fichier uploadé est utilisé.
  • twofa_type (chaîne, optionnel): Type de 2FA (mail ou sms, par défaut : mail)

Pour chaque fichier dans files[], vous pouvez fournir soit :

  • path: Chemin d'un fichier uploadé sur S3 (depuis l'interface web ou une URL présignée)
  • url: URL d'un fichier PDF distant (l'API le téléchargera et le stockera sur S3)

Si path et url sont fournis, path est utilisé.

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"
}

Exemple de requête (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)

Exemple de réponse (succès)

{
  "status": "success",
  "message": "Lien envoyé aux destinataires.",
  "data": {
    "secure_download_id": 123,
    "token": "...",
    "expires_at": "2025-06-01T12:00:00",
    "link": "https://gesdocs.fr/secure-downloads/123"
  }
}

Exemple de réponse (erreur)

{
  "status": "error",
  "message": "Impossible de télécharger le fichier depuis l'URL fournie.",
  "field": "files.0.url"
}
{
  "status": "error",
  "message": "Le fichier à l'URL fournie n'est pas un PDF valide.",
  "field": "files.0.url"
}
{
  "status": "error",
  "message": "Impossible de télécharger le logo depuis l'URL fournie.",
  "field": "logo_url"
}
{
  "status": "error",
  "message": "Le fichier à l'URL fournie n'est pas une image valide.",
  "field": "logo_url"
}

Si vous fournissez une URL de fichier ou de logo distante, l'API tentera de la télécharger et de la stocker. Si le fichier n'est pas accessible ou invalide, une erreur sera retournée.