BunnyDoc
APIE-Signing API

Send from a template

Create an envelope from one of your templates and send it in a single call, then retrieve the signing links.

This is the endpoint most integrations are built around: take one of your templates, assign real people to its roles, and send it for signature — all in one call. There is no draft step on the API.

Create an envelope from a template and send it

Requires the envelopes:send scope. Creating and sending happen together: if the send fails for any reason, the envelope is deleted and an error is returned, so you never leave a half-created draft behind. Each successful send consumes one of your plan's API signature requests.

Endpoint

POST   https://api2.bunnydoc.com/v1/envelopes/from-template

Body

FieldTypeRequiredNotes
template_idstring (uuid)YesThe template to send. Get it from GET /v1/templates.
recipientsarrayYes1–50 recipients, one per unlocked template role.
sender_emailstringNoSend as this user. Must be an active user in your company with an eSignature seat. Defaults to the API key's owner.
titlestringNoEnvelope title, up to 250 characters. Defaults to the template name.
email_subjectstringNoOverrides the subject line of the signing email. Up to 300 characters. Defaults to the template's subject.
email_messagestringNoOverrides the message body shown to recipients in the signing email. Up to 5000 characters. Defaults to the template's message (or your active brand default).

Each recipient maps a real person to a role on the template:

Recipient fieldTypeRequiredNotes
rolestringYesMust match an unlocked role from GET /v1/templates/{id}. Up to 25 characters.
namestringYesRecipient's full name, up to 120 characters.
emailstringYesRecipient's email, up to 150 characters.
contact_numberstringNoUp to 20 characters.

Match roles exactly, and skip locked ones

Each role must be an unlocked role name from the template, and each role may appear once. A role that doesn't exist, or a locked role, is rejected with unknown_signer_role. Always call GET /v1/templates/{id} first to read the valid roles.

Example request

Send from a template
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" }
    ]
  }'

Response

201 Created
{
  "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"
}
FieldTypeDescription
envelope_idstringThe new envelope's id.
statusstringAlways sent on success.
senderobjectThe resolved sender's email.
recipientsarrayThe recipients you supplied.
signing_urlsarray | nullPresent only if the envelope shares signing links with the sender; otherwise null. See below.
created_atstringISO 8601 timestamp.

Where do expiry, reminders and fields come from?

Expiry, reminders, signing order, and field layout are inherited from the template. The API sets the recipients, the title, the sender, and — when you provide them — the email subject and message; the template (and your active brand default) supply the rest.

Errors

Statuserror.codeWhen it happens
402quota_exceededYour company has no remaining API signature requests for this period.
404template_not_foundNo template with that id exists in your company.
422unknown_signer_roleA recipient role doesn't match the template, or a locked role was supplied.
422sender_not_foundsender_email isn't an active user with an eSignature seat in your company.
422validation_failedThe body is malformed (missing field, duplicate role, out-of-range value).
429rate_limitedMore than 100 sends in 15 minutes for this key.

Signing links let the sender's system hand each recipient a direct link instead of waiting for the email. They're available any time after sending, and are also returned inline by the send call above.

Endpoint

GET   https://api2.bunnydoc.com/v1/envelopes/{id}/signing-links

Example request

Get signing links
curl https://api2.bunnydoc.com/v1/envelopes/018f9a0b-1c2d-7e3f-8a4b-5c6d7e8f9a0b/signing-links \
  -H "Authorization: Bearer <access_token>"

Response

200 OK
{
  "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 is null for recipients who don't sign (for example, a "receives a copy" recipient).

A signing URL is a bearer credential

Anyone holding a signing URL can sign as that recipient. Deliver them over secure channels and treat them like secrets — don't log them or put them in URLs you share.

Errors

Statuserror.codeWhen it happens
403signing_links_disabledThis envelope doesn't have "share signing links with sender" enabled.
404envelope_not_foundNo envelope with that id exists in your company.

Want status updates without polling?

The API is write-only for envelopes — there's no status endpoint by design. To know when a document is viewed, signed, or completed, subscribe to webhooks.

On this page