BunnyDoc
APIE-Signing API

Create and manage API keys

Mint an API key, choose its scopes, set an expiry, and rotate or revoke it — everything you need before your first API call.

An API key is the long-lived credential behind every integration. You never send it on ordinary requests: you exchange it once for a short-lived access token, and the token does the work.

Keys are managed in the app, not over the API — there is deliberately no endpoint that mints a credential.

Where

Settings → API Keys. Visible to owners and admins only, and only when your plan includes API access.

Before you start: is API access in your plan?

API access is sold separately from the rest of BunnyDoc. Without it:

  • the API Keys screen refuses to create a key, and
  • POST /v1/auth/token returns 403 forbidden even for a key that already exists.

Check Settings → Billing → Resources for two entries:

ResourceWhat it controls
API accessWhether /v1 works at all, and whether you can mint keys.
API signature requestsHow many envelopes you may send through the API per period — one unit per envelope.

If either is missing or at zero, talk to us about adding it before you build.

Create a key

Name it after the integration, not the person

Zapier — production, Billing sync, Staging sandbox. The name is how you'll recognise it when you rotate or revoke months later, and it's all you'll have to go on — the key itself is never shown again.

Pick the narrowest set of scopes

Scopes are per key. Grant only what the integration calls — see the table below.

Optionally set an expiry

Leave it blank and the key never expires. Set a future date and the key stops working then, returning the same 401 as an unknown key. An expiry is good hygiene for a key you hand to a third party or use for a time-boxed migration.

Copy the key immediately

The key looks like bd_live_… and is displayed exactly once, at creation. It is stored hashed on our side, so we cannot show it to you again — if you lose it, rotate the key to mint a new secret.

Keep the key server-side

A key acts on behalf of your whole company. Never put it in a browser, a mobile app, a repository, or any client you don't control. Load it from an environment variable or a secret manager.

Scopes

A scope lets a key do something. It can never let the key do more than the person who created it — the two are intersected on every request, so if that person loses a permission in the app, their keys lose it at the same moment.

ScopeUnlocks
templates:readGET /v1/templates, GET /v1/templates/{id}
contacts:readGET /v1/contacts
contacts:writePOST /v1/contacts
envelopes:sendPOST /v1/envelopes/from-template, GET /v1/envelopes/{id}/signing-links
webhooks:readGET /v1/webhooks, GET /v1/webhooks/events
webhooks:writePOST /v1/webhooks, DELETE /v1/webhooks/{id}
users:readGET /v1/users

Every key needs at least one scope. A typical send-and-track integration needs templates:read, envelopes:send, webhooks:read and webhooks:write — and nothing else.

Two independent gates

Calling an endpoint requires both the scope on the key and the matching permission on its owner. A key with templates:read whose owner can't read templates in the app gets 403 forbidden, not a result. Missing scope gives you 403 insufficient_scope instead, so the two failures are easy to tell apart.

How many keys can I have?

Your plan sets the number of active keys per company. When you hit it, creating another is refused until you revoke one. Revoked keys don't count.

Use separate keys per environment and per integration — it's the only way to revoke one thing without breaking the rest.

Rotate a key

Rotation issues a new secret on the same key record, keeping its name, scopes and expiry. Use it for scheduled credential hygiene.

Rotation is not reversible:

  • the new key is displayed once — copy it, then deploy it;
  • the old secret can no longer be exchanged for a token, so POST /v1/auth/token with it returns 401 invalid_api_key;
  • access tokens already minted from the old secret keep working until they expire — up to one hour.

So a rotation is a clean hand-over for your own deployment: finish the rollout within the hour and no request fails.

If a key has leaked, revoke it — don't just rotate it

Rotation closes the door on new tokens but leaves any token already issued from the old secret valid for the remainder of its hour. To cut off access immediately, revoke the key and mint a fresh one.

Revoke a key

Revoking kills the key permanently, and it is the action that takes effect immediately:

  • the key can never be exchanged for a token again, and
  • every outstanding token minted from it fails on its next request, with 401 key_revoked — you don't wait out the token's hour.

This is the right response to a suspected leak, a departing contractor, or an integration you're switching off.

What your integration should do about key errors

You getWhat happenedDo this
401 invalid_api_key on /auth/tokenThe key is unknown, revoked, expired, or not live-mode — we don't say whichStop retrying. Check the key in Settings → API Keys.
403 forbidden on /auth/tokenAPI access isn't in the planStop retrying. This is a billing change, not a code change.
401 invalid_token on any other callThe token expiredExchange the key for a new token and retry once.
401 key_revoked on any other callThe key behind the token was revokedStop retrying with the cached token. Load the replacement key.
403 insufficient_scopeThe key lacks a scopeAdd the scope to the key (or mint one that has it).

Don't mint a token per request

POST /v1/auth/token is capped at 20 requests per 15 minutes, per IP, because a healthy integration needs roughly one token an hour. Cache the token for its full expires_in and refresh shortly before it lapses.

Next steps

On this page