Khatm
Sandbox API Khatm
Intégrez le parcours de signature Khatm directement dans votre application.
Créez des demandes, détectez et confirmez les champs, relancez les signataires, annulez un parcours et récupérez les documents finalisés avec leurs preuves.
Démarrage rapide
- Créez une clé sandbox depuis l’onglet Sandbox API de votre espace. Copiez la clé khatm_test_… et le secret webhook whsec_… : ils ne sont affichés qu'une seule fois.
- Créez une demande avec le PDF et vos signataires :
curl "$KHATM_BASE_URL/v1/signature-requests" \
-H "Authorization: Bearer $KHATM_API_KEY" \
-F "document=@contract.pdf;type=application/pdf" \
-F 'request={
"client_reference": "contract-123",
"signers": [{ "reference": "customer", "name": "Alice Martin",
"email": "alice@example.com", "order": 1 }],
"fields": [{ "signer_reference": "customer", "type": "signature",
"page": 1, "x": 90, "y": 610, "width": 170, "height": 55 }]
}'- Activez-la avec POST /signature-requests/{id}/activate pour obtenir un signing_url par signataire.
- Suivez l'état par webhook ou avec GET /signature-requests/{id}, puis téléchargez le PDF signé et les preuves via /artifacts/{type}.
Pas de coordonnées sous la main ? Omettez fields, appelez POST /signature-requests/{id}/detect-fields, puis confirmez les suggestions avec PUT /signature-requests/{id}/fields.
Retour vers votre application
Ajoutez return_url à la création : après sa signature (ou un refus), le signataire revient automatiquement dans votre application. Khatm ajoute khatm_status (signed, declined, cancelled ou expired), signature_request_id, client_reference et signer_reference. Servez-vous-en pour l’affichage, puis confirmez le résultat avec l’API ou un webhook.
Autres options utiles :
- locale (fr, en, ar) par signataire fixe la langue de la page de signature.
- sequential_signing: true impose l’ordre des signataires (order).
- GET /signature-requests liste vos demandes (filtres status, client_reference, pagination par cursor).
- POST /templates crée un modèle réutilisable par API.
Changer un signataire
Une adresse erronée ou un départ ? POST /v1/signature-requests/{id}/signers/{reference}/replace avec email (et name, locale, send_email). Avant activation, le signataire est simplement corrigé. Après activation, l’ancien lien est révoqué et le nouveau signataire reprend la même référence, le même ordre et les mêmes champs ; la réponse contient son nouveau signing_url. Un signataire qui a déjà signé ou refusé ne peut plus être remplacé (409).
Modèles de signature
Un modèle enregistre une fois l’emplacement des signatures et des champs d’un contrat type. Pour chaque nouveau contrat qui suit la même mise en page, vous envoyez le PDF et l’identifiant du modèle : plus besoin de coordonnées.
Dans votre espace
- Ouvrez la page Modèles de signature et créez un modèle à partir du PDF de référence.
- Choisissez le nombre de signataires, puis placez les signatures et les champs d’information.
- Enregistrez, puis copiez le template_id depuis la liste.
Par API
Créez le modèle avec POST /v1/templates (multipart : document, name, fields). Envoyez ensuite chaque demande avec le PDF à signer et template_id à la place de fields :
{
"client_reference": "contrat-2026-0042",
"template_id": "7f331696-d933-46cd-aeff-1c08151c85c1",
"signers": [{
"reference": "signer_1", "name": "Alice Martin",
"email": "alice@example.com", "order": 1
}],
"field_values": { "contract_amount": "1 200 EUR" }
}À savoir
- Chaque signer_reference du modèle (par exemple signer_1) est un rôle : vos demandes doivent utiliser les mêmes références de signataires.
- field_values remplit les champs nommés du modèle, comme contract_amount ci-dessus.
- template_id et fields ne se combinent pas dans une même demande.
- GET /v1/templates liste vos modèles prêts.
- DELETE /v1/templates/{id} archive un modèle : il ne sert plus aux nouvelles demandes, celles déjà créées ne changent pas.
Modèles d’e-mail
Un modèle d’e-mail définit l’apparence des e-mails envoyés à vos signataires : nom d’expéditeur, logo, objet et message. Vous le créez une fois, puis vous l’indiquez dans chaque demande.
Dans votre espace
- Ouvrez la page Modèles d’e-mail et cliquez sur Nouveau modèle d’e-mail.
- Renseignez le nom d’expéditeur, le logo, l’objet et le message. L’aperçu montre le rendu en français, en anglais et en arabe.
- Enregistrez, puis copiez l’identifiant ebr_… depuis la liste.
Par API
Créez le modèle avec POST /v1/email-brands (le logo doit être en HTTPS) :
{
"sender_name": "Cabinet Benali",
"subject": "Votre contrat est prêt à signer",
"message": "Merci de signer votre contrat avant vendredi.",
"logo_url": "https://example.com/logo.png"
}Indiquez ensuite son identifiant à la création de chaque demande :
{
"client_reference": "contrat-2026-0042",
"email_brand_id": "ebr_…",
"signers": [ … ]
}À savoir
- Le modèle s’applique aux invitations, aux rappels et aux e-mails envoyés à un nouveau signataire après un remplacement.
- Chaque e-mail part dans la langue locale du signataire : fr, en ou ar (de droite à gauche pour l’arabe).
- Sans email_brand_id, Khatm envoie son e-mail standard.
- Un modèle est partagé par toutes les clés API du compte.
- Un modèle archivé ne peut plus servir à de nouvelles demandes.
- Pour un cas ponctuel, vous pouvez envoyer un objet email avec la demande à la place de email_brand_id (les deux ne se combinent pas).
Envoi en masse
POST /v1/bulk-sends envoie un modèle à 50 destinataires au maximum en un appel : chaque destinataire (client_reference, signers, field_values) devient une demande créée et activée. Le résultat est donné ligne par ligne (active, already_exists ou error) ; une ligne invalide n’empêche pas les autres. Relancer le même lot ne crée aucun doublon et ne renvoie aucun e-mail.
Vérifier l’identité du signataire
Ajoutez "verification": "email_otp" à un signataire. Avant de voir le document, il reçoit un code à 6 chiffres par e-mail (valable 10 minutes, 5 essais). Le document, la signature et le refus restent bloqués côté serveur tant que le code n’est pas saisi. La vérification apparaît dans le statut (verified_at) et dans les preuves.
Intégrer la signature dans votre application
Indiquez embed_origin (par exemple https://app.exemple.com) à la création. L’activation renvoie alors un embed_url par signataire, à charger dans une <iframe> sur cette origine ; aucun autre site ne peut l’afficher. La page envoie à votre fenêtre des messages postMessage (signing.loaded, signing.verification_required, signing.signed, signing.declined, et signing.closed avec un status si le lien n’est plus utilisable) contenant signatureRequestId, clientReference et signerReference. Vérifiez event.origin et confirmez le résultat par webhook ou via le statut.
SDK
Des clients Node.js, Python et PHP sans dépendance sont disponibles dans le dépôt (sdks/). Ils ajoutent automatiquement un Idempotency-Key, relancent les réponses 429 et 503, et vérifient les webhooks.
Authentification
Chaque requête envoie la clé dans l'en-tête Authorization: Bearer khatm_test_…. Traitez-la comme un mot de passe : gardez-la côté serveur, jamais dans le navigateur, une URL ou des logs. Une clé révoquée est refusée immédiatement.
Recevoir les webhooks
- Indiquez votre adresse : ajoutez callback_url (HTTPS) à chaque demande. Khatm y envoie un POST JSON à chaque changement d’état de la demande ou d’un signataire.
- Gardez le secret : chaque clé API a son secret whsec_…, affiché à la création de la clé. Vous pouvez l’afficher à nouveau depuis la page Sandbox API (bouton Secret webhook). Il sert à vérifier chaque événement (voir ci-dessous).
- Répondez vite : renvoyez un code 2xx dès réception, puis traitez l’événement. Sans réponse 2xx, Khatm réessaie automatiquement.
- Suivez les livraisons dans votre espace, page Webhooks : chaque événement avec son état, son contenu, et un bouton pour le renvoyer.
Vérifier les webhooks
Khatm signe webhook-id + "." + webhook-timestamp + "." + corps brut en HMAC-SHA256 avec votre secret whsec_…. L'en-tête webhook-signature vaut v1, suivi de la signature en base64.
- Vérifiez les octets bruts avec une comparaison à temps constant.
- Rejetez les horodatages trop anciens.
- Dédupliquez avec webhook-id : la livraison est « au moins une fois », avec nouvelles tentatives (immédiate, puis environ 1 min, 5 min, 30 min et 2 h).
Événements : signature_request.activated, signer.viewed (premier accès au lien), signer.completed, signer.declined, signer.replaced, signer.expired, puis signature_request.completed, .declined, .cancelled ou .expired. Les événements de signataire contiennent data.signer (référence, e-mail, statut). L’ordre d’arrivée n’est pas garanti : en cas de doute, relisez GET /v1/signature-requests/{id}.
Suivi et rejeu : GET /v1/webhook-deliveries liste chaque événement avec son état (pending, delivered, failed) et sa dernière erreur. Après avoir corrigé votre récepteur, POST /v1/webhook-deliveries/{id}/replay renvoie l’événement immédiatement, avec le même webhook-id.
Limites et conservation
- PDF de 8 Mio maximum, jusqu'à 10 signataires et 100 champs par demande.
- Dépassement du débit : réponse 429, avec les en-têtes X-RateLimit-Limit et X-RateLimit-Remaining.
- Indisponibilité passagère : réponse 503 temporarily_unavailable. Réessayez avec un délai croissant ; rejouer une création avec la même client_reference ne crée jamais de doublon.
- Les contenus sont supprimés 10 jours après l'import : téléchargez le PDF signé et les preuves avant retention_expires_at.
API v1
POST /v1/signature-requestsRéunissez le PDF, les signataires et les champs dans une demande. Une référence client relie la signature à votre métier.POST /v1/signature-requests/{id}/activateActivez la demande pour obtenir les liens de signature. Intégrez chaque URL au parcours de la bonne personne.URL Parcours de signature KhatmLe signataire ouvre son lien, consulte le document et complète les champs prévus pour lui.EVENT signature_request.completedVotre application reçoit l’événement de fin. Vérifiez son authenticité avant de mettre à jour votre workflow.GET /v1/signature-requests/{id}/artifacts/{type}Récupérez le document finalisé et les preuves associées, puis rattachez-les à votre dossier client.