BunnyDoc
APIE-Signing API

E-Signing API

Send documents for signature straight from your own systems — exchange an API key for a token, create envelopes from templates, manage contacts, and retrieve signing links over a simple REST API.

The E-Signing API lets your application do what your team does in the app: turn a template into a signature request, send it, and follow it through to a signed, audit-trailed PDF — without anyone opening BunnyDoc.

It's a small, focused REST API. JSON in, JSON out, one bearer token, and the exact same permissions your team already has in the app.

Base URL

Every endpoint lives under https://api2.bunnydoc.com/v1. All paths on these pages are relative to that base.

How authentication works

Access is a two-step flow, and it's the first thing you'll build. Your long-lived API key is sent once to get a short-lived access token; every other request carries only the token, so the key never travels again.

Create an API key

In the app, open Settings → API Keys (owner or admin only) and create a key. It looks like bd_live_… and is shown once, at creation — copy it somewhere safe. You can't retrieve it afterwards, only rotate it.

Exchange the key for an access token

Send your key to POST /v1/auth/token. You get back a bearer token that's valid for one hour.

Call the API with the token

Send Authorization: Bearer <token> on every other request. Cache the token and reuse it until it expires — don't mint a new one per call.

Keep your API key server-side

An API key acts on behalf of your whole company. Never ship it in a browser, a mobile app, or any client you don't control. If a key is exposed, rotate it from Settings → API Keys — rotating (or revoking) invalidates its outstanding tokens immediately.

Start here

Endpoints at a glance

Each request is authorised by both the scope on your key and the permission of the user who owns it — a key can never do more than that person can in the app.

Do thisEndpointScope
Exchange an API key for a tokenPOST /v1/auth/token
List your templatesGET /v1/templatestemplates:read
Get one template and its rolesGET /v1/templates/{id}templates:read
List contactsGET /v1/contactscontacts:read
Create a contactPOST /v1/contactscontacts:write
Create an envelope from a template and send itPOST /v1/envelopes/from-templateenvelopes:send
Retrieve signing links for a sent envelopeGET /v1/envelopes/{id}/signing-linksenvelopes:send
List the events you can subscribe toGET /v1/webhooks/eventswebhooks:read
List your webhook subscriptionsGET /v1/webhookswebhooks:read
Subscribe an endpoint to eventsPOST /v1/webhookswebhooks:write
Unsubscribe an endpointDELETE /v1/webhooks/{id}webhooks:write

Want to be notified when a document is signed, declined or voided instead of polling? Use webhooks — and take the finished PDF straight from the envelope.document_ready payload.

Conventions

  • JSON in, JSON out — send and expect application/json.
  • Scoped to your company — every resource belongs to one company, and requests never cross company boundaries.
  • Same permissions as the app — a key can only do what its owner's role allows. See Users & roles.
  • Scopes narrow access — the scopes on a key (templates:read, contacts:read, contacts:write, envelopes:send, webhooks:read, webhooks:write) can only ever restrict what its owner could already do, never extend it.

Pagination

List endpoints take page (from 1) and per_page (up to 100, default 25), and return a pagination object:

{
  "data": [ /* … */ ],
  "pagination": { "page": 1, "per_page": 25, "total": 134, "total_pages": 6 }
}

Rate limits

Requests are throttled per API key (the token endpoint is per IP). Exceeding a limit returns 429 rate_limited — back off and retry.

LimitScope
20 token exchanges / 15 minper IP
100 sends / 15 minper API key
1000 other requests / 15 minper API key

Errors

Every error has the same shape — branch on error.code, never on the message text. See the full error reference.

{ "error": { "code": "unknown_signer_role", "message": "…", "details": { } } }

On this page