Envoyer depuis un modèle
Créez une enveloppe à partir d'un de vos modèles et envoyez-la en un seul appel, puis récupérez les liens de signature.
C'est l'endpoint autour duquel la plupart des intégrations sont construites : prenez un de vos modèles, affectez de vraies personnes à ses rôles et envoyez-le pour signature — le tout en un seul appel. Il n'y a pas d'étape de brouillon sur l'API.
Créer une enveloppe à partir d'un modèle et l'envoyer
Requiert le scope envelopes:send. La création et l'envoi ont lieu ensemble : si l'envoi échoue pour
une raison quelconque, l'enveloppe est supprimée et une erreur est renvoyée, de sorte que vous ne
laissez jamais de brouillon à moitié créé. Chaque envoi réussi consomme une des demandes de
signature par API de votre plan.
Endpoint
POST https://api2.bunnydoc.com/v1/envelopes/from-template
Corps
| Champ | Type | Requis | Notes |
|---|---|---|---|
template_id | string (uuid) | Oui | Le modèle à envoyer. Obtenez-le via GET /v1/templates. |
recipients | array | Oui | De 1 à 50 destinataires, un par rôle déverrouillé du modèle. |
sender_email | string | Non | Envoyer en tant que cet utilisateur. Doit être un utilisateur actif de votre entreprise disposant d'un siège de signature électronique. Par défaut, le propriétaire de la clé d'API. |
title | string | Non | Titre de l'enveloppe, jusqu'à 250 caractères. Par défaut, le nom du modèle. |
email_subject | string | Non | Objet des e-mails d'invitation (et de rappel). Jusqu'à 300 caractères. Accepte les placeholders. Par défaut, l'objet du modèle, ou New Document for Signature - {title}. |
email_message | string | Non | Message présenté aux destinataires. Jusqu'à 10 000 caractères. Texte brut ou HTML limité, et accepte les placeholders. Par défaut, le message du modèle, ou celui par défaut de votre marque active. |
Chaque destinataire associe une personne réelle à un rôle du modèle :
| Champ du destinataire | Type | Requis | Notes |
|---|---|---|---|
role | string | Oui | Doit correspondre à un rôle déverrouillé de GET /v1/templates/{id}. Jusqu'à 25 caractères. |
name | string | Oui | Nom complet du destinataire, jusqu'à 120 caractères. |
email | string | Oui | E-mail du destinataire, jusqu'à 150 caractères. |
contact_number | string | Non | Jusqu'à 20 caractères. |
Faites correspondre les rôles exactement, et ignorez les verrouillés
Chaque role doit être le nom d'un rôle déverrouillé du modèle, et chaque rôle peut apparaître une
fois. Un rôle qui n'existe pas, ou un rôle verrouillé, est rejeté avec unknown_signer_role.
Appelez toujours d'abord GET /v1/templates/{id} pour lire les
rôles valides.
Ne mettez pas l'expéditeur dans recipients
recipients concerne les personnes qui reçoivent le document. L'expéditeur est celui que
sender_email résout, et sa part du modèle — le rôle Me — est ajoutée et complétée pour vous. Vous
ne transmettez jamais de destinataire Me ; si vous le faites, son nom et son e-mail sont ignorés au
profit du véritable expéditeur.
Exemple de requête
curl -X POST https://api2.bunnydoc.com/v1/envelopes/from-template \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"template_id": "018f2c3d-4e5f-7a8b-9c0d-1e2f3a4b5c6d",
"title": "Mutual NDA — Acme Corp",
"sender_email": "sales@yourco.com",
"email_subject": "Please sign: Mutual NDA",
"email_message": "Hi Jane — please review and sign our mutual NDA. Thanks!",
"recipients": [
{ "role": "Client", "name": "Jane Doe", "email": "jane@acme.com" }
]
}'POST /v1/envelopes/from-template HTTP/1.1
Host: api2.bunnydoc.com
Authorization: Bearer <access_token>
Content-Type: application/json
{
"template_id": "018f2c3d-4e5f-7a8b-9c0d-1e2f3a4b5c6d",
"title": "Mutual NDA — Acme Corp",
"sender_email": "sales@yourco.com",
"email_subject": "Please sign: Mutual NDA",
"email_message": "Hi Jane — please review and sign our mutual NDA. Thanks!",
"recipients": [
{ "role": "Client", "name": "Jane Doe", "email": "jane@acme.com" }
]
}Réponse
{
"envelope_id": "018f9a0b-1c2d-7e3f-8a4b-5c6d7e8f9a0b",
"status": "sent",
"title": "Mutual NDA — Acme Corp",
"sender": { "email": "sales@yourco.com" },
"recipients": [
{ "role": "Client", "name": "Jane Doe", "email": "jane@acme.com" }
],
"signing_urls": [
{
"recipient_id": "018f9a0b-2c3d-7e4f-8a5b-6c7d8e9f0a1b",
"name": "Jane Doe",
"email": "jane@acme.com",
"recipient_type": "need-to-sign",
"signing_url": "https://sign.bunnydoc.com/s/eyJhbGciOi…"
}
],
"created_at": "2026-07-28T10:20:00.000Z"
}| Champ | Type | Description |
|---|---|---|
envelope_id | string | L'id de la nouvelle enveloppe. |
status | string | Toujours sent en cas de succès. |
sender | object | L'e-mail de l'expéditeur résolu. |
recipients | array | Les destinataires que vous avez fournis. |
signing_urls | array | null | Présent uniquement si l'enveloppe partage les liens de signature avec l'expéditeur ; sinon null. Voir ci-dessous. |
created_at | string | Horodatage ISO 8601. |
D'où viennent l'expiration, les rappels et les champs ?
L'expiration, les rappels, l'ordre de signature et la disposition des champs sont hérités du modèle. L'API définit les destinataires, le titre, l'expéditeur et — lorsque vous les fournissez — l'objet et le message de l'e-mail ; le modèle (et le paramètre par défaut de votre marque active) fournissent le reste.
Personnaliser l'e-mail d'invitation
email_subject et email_message déterminent l'e-mail que reçoit chaque destinataire (ainsi que
les rappels qui suivent : les rappels réutilisent l'objet, préfixé Reminder:). Si vous les
omettez, les valeurs du modèle sont utilisées.
Placeholders
Les deux champs acceptent des placeholders, remplis pour chaque destinataire au moment de l'envoi. Un seul appel peut donc produire un e-mail nominatif pour chaque signataire.
| Placeholder | Devient |
|---|---|
{{recipient_name}} | Le nom complet du destinataire |
{{recipient_first_name}} | Le prénom du destinataire |
{{recipient_email}} | L'adresse e-mail du destinataire |
{{sender_name}} | Le nom complet de l'expéditeur |
{{sender_first_name}} | Le prénom de l'expéditeur |
{{sender_email}} | L'adresse e-mail de l'expéditeur |
{{company_name}} | Le nom de votre entreprise |
{{envelope_title}} | Le titre de l'enveloppe |
{{expiry_date}} | La date d'expiration de l'enveloppe, formatée selon ses paramètres régionaux |
{
"template_id": "018f2c3d-4e5f-7a8b-9c0d-1e2f3a4b5c6d",
"email_subject": "{{recipient_first_name}}, merci de signer {{envelope_title}}",
"email_message": "<p>Bonjour {{recipient_first_name}},</p><p>Merci de relire et de signer. Expire le {{expiry_date}}.</p><p>Cordialement,<br/>{{sender_name}}</p>",
"recipients": [
{ "role": "Client", "name": "Jane Doe", "email": "jane@acme.com" },
{ "role": "Witness", "name": "Sam Ortiz", "email": "sam@acme.com" }
]
}Un placeholder inconnu est rejeté, pas ignoré
Tout ce qui figure entre {{ … }} et n'est pas dans la liste ci-dessus fait échouer la requête avec
validation_failed : nous n'enverrons pas un e-mail contenant un {{customer_ref}} littéral.
Vérifiez l'orthographe par rapport au tableau ; les noms sont exacts et en minuscules.
Il n'existe volontairement aucun placeholder pour le lien de signature ni pour le code d'accès.
L'e-mail comporte déjà le bouton de signature, et un code d'accès est un second facteur qui doit
parvenir au destinataire par un autre canal. Utilisez
GET /v1/envelopes/{id}/signing-links si
votre propre système a besoin de l'URL.
Mise en forme dans email_message
Envoyez du texte brut (les sauts de ligne sont conservés) ou un petit sous-ensemble sûr de HTML :
| Autorisé | Balises |
|---|---|
| Paragraphes et sauts | <p>, <br> |
| Emphase | <strong>, <b>, <em>, <i>, <u>, <s> |
| Listes | <ul>, <ol>, <li> |
| Liens | <a href> — https, http, mailto, tel uniquement |
Tout le reste est supprimé à l'entrée, y compris style, class, id, les images, les tableaux et
les titres. La valeur enregistrée est la version nettoyée : ce que vous pouvez enregistrer est donc
exactement ce que le destinataire reçoit.
Les liens dont le texte contredit la cible sont rejetés
<a href="https://evil.example">https://yourbank.example</a> échoue avec validation_failed. Si le
texte du lien ressemble à une adresse, ce doit être l'adresse vers laquelle vous pointez. Utilisez un
texte descriptif (<a href="https://acme.example/terms">nos conditions</a>) et le problème ne se
pose jamais.
La limite de 10 000 caractères est comptée après nettoyage : un peu de balisage superflu ne vous fera donc pas dépasser.
Erreurs
| Statut | error.code | Quand cela se produit |
|---|---|---|
402 | quota_exceeded | Votre entreprise n'a plus de demandes de signature par API pour cette période. Rien n'a été livré. |
404 | template_not_found | Aucun modèle avec cet id n'existe dans votre entreprise. |
422 | unknown_signer_role | Un rôle de destinataire ne correspond pas au modèle, ou un rôle verrouillé a été fourni. |
422 | sender_not_found | sender_email n'est pas un utilisateur actif disposant d'un siège de signature électronique dans votre entreprise. (Sans sender_email, le propriétaire de la clé a perdu son siège.) |
422 | sender_fields_incomplete | Le rôle expéditeur du modèle a des champs obligatoires sans valeur : le document ne peut pas partir. Corrigez-le sur le modèle — voir la référence des erreurs. |
400 422 | validation_failed | Le corps est mal formé — champ manquant, rôle en double, limite de longueur dépassée, {{placeholder}} inconnu ou lien trompeur. |
429 | rate_limited | Plus de 100 envois en 15 minutes pour cette clé. |
5xx | send_failed | Créée mais non envoyée, donc supprimée. Rien n'a été livré ; réessayer crée une nouvelle enveloppe plutôt que d'en dupliquer une. |
Obtenir les liens de signature d'une enveloppe envoyée
Les liens de signature permettent au système de l'expéditeur de remettre à chaque destinataire un lien direct au lieu d'attendre l'e-mail. Ils sont disponibles à tout moment après l'envoi et sont aussi renvoyés directement par l'appel d'envoi ci-dessus.
Endpoint
GET https://api2.bunnydoc.com/v1/envelopes/{id}/signing-links
Exemple de requête
curl https://api2.bunnydoc.com/v1/envelopes/018f9a0b-1c2d-7e3f-8a4b-5c6d7e8f9a0b/signing-links \
-H "Authorization: Bearer <access_token>"GET /v1/envelopes/018f9a0b-1c2d-7e3f-8a4b-5c6d7e8f9a0b/signing-links HTTP/1.1
Host: api2.bunnydoc.com
Authorization: Bearer <access_token>Réponse
{
"signing_urls": [
{
"recipient_id": "018f9a0b-2c3d-7e4f-8a5b-6c7d8e9f0a1b",
"name": "Jane Doe",
"email": "jane@acme.com",
"recipient_type": "need-to-sign",
"signing_url": "https://sign.bunnydoc.com/s/eyJhbGciOi…"
}
]
}signing_url vaut null pour les destinataires qui ne signent pas (par exemple, un destinataire qui
« reçoit une copie »).
Un lien de signature est une donnée d'authentification
Quiconque détient un lien de signature peut signer en tant que ce destinataire. Transmettez-les par des canaux sécurisés et traitez-les comme des secrets : ne les journalisez pas et ne les mettez pas dans des URL que vous partagez.
Erreurs
| Statut | error.code | Quand cela se produit |
|---|---|---|
403 | signing_links_disabled | Cette enveloppe n'a pas l'option « partager les liens de signature avec l'expéditeur » activée. |
404 | envelope_not_found | Aucune enveloppe avec cet id n'existe dans votre entreprise. |
Vous voulez les mises à jour de statut sans interroger l'API ?
L'API est en écriture seule pour les enveloppes : il n'y a pas d'endpoint de statut, par conception. Pour savoir quand un document est vu, signé ou terminé, abonnez-vous aux webhooks.
Utilisateurs
Listez les membres de votre entreprise pour que votre intégration permette de choisir au nom de qui une enveloppe est envoyée.
Webhooks
Recevez des événements en temps réel — enveloppe envoyée, vue, signée, terminée, et plus — poussés vers un endpoint HTTPS que vous contrôlez, sans jamais interroger l'API.