Skip to content

Authentication

Bearer API keys, issued per project, used from a server. How a key is shaped, what the two halves are for, and how to replace one without an outage.

An API key is a server-side credential. Never put one in a browser.

Not in front-end JavaScript, not in a mobile application binary, not in a desktop app you distribute, not in a public repository, and not in a URL. Anything shipped to a device can be read off that device. A key found in a browser bundle is a key that can be used by anyone who opens the page, against your quota, until you revoke it — and the Developer and API Terms make keeping it secret your responsibility.

If a key has been exposed, create a replacement and revoke the exposed one. Revocation takes effect on the next request; no redeployment of this API is involved.

Every request carries the key as a bearer token.

http
Authorization: Bearer $EDOCUMENT_API_KEY

There is no query-parameter form and no cookie form. A credential in a URL is written into access logs, browser history, referrer headers and proxy logs, so this API does not accept one there at all.

What a key looks like

A key has two halves separated by an underscore, and they are not equally secret.

text
edt_live_<key id>_<43-character secret>
  • The prefix — edt_live_ plus a sixteen-character key id — identifies the key. It is not a secret: it appears in the dashboard and in this deployment's own operational logs, so that a request can be traced to a key without the secret ever being written down. It is the handle you use to talk about a key, and it is safe to paste into a support message.
  • The secret — the 43 characters after the second underscore — is stored as a SHA-256 digest and never in a recoverable form. It is displayed exactly once, when the key is created.

live and test appear in the middle of the prefix. They are a label on the key, not two different services: both run against the same validation engine and the same data. The point is that a key pasted into the wrong configuration is visibly the wrong key.

Why the secret is shown once

Because a secret that can be retrieved is a secret that can be retrieved by whoever gets into your dashboard. Storing it in a recoverable form would mean a database dump is a set of working credentials; storing the digest means it is not. The trade is that losing the secret costs you a key replacement rather than a lookup, which is the right way round.

Restricting a key to specific targets

A key can be limited to a named set of target ids when it is created. A key that is only ever going to validate French documents has no reason to be able to validate Greek ones, and a restricted key that leaks does less.

A request for a target outside a key's set is refused with forbidden_target and HTTP 403 — distinct from unknown_target, which means no such target exists at all. The difference matters when you are debugging: one is a configuration problem, the other is a typo.

The targets a key may use are listed by the catalogue endpoint, using that key:

bash
curl https://edocumenttools.com/api/v1/targets \
  -H "Authorization: Bearer $EDOCUMENT_API_KEY"

Replacing a key without an outage

There is no in-place rotation, and that is deliberate: an endpoint that swapped a secret behind an unchanged prefix would break every running process at once, at a moment of its choosing rather than yours. Replacement is three steps you control.

  1. Create the replacement. Both keys now work. Your key limit has to have room for two, which is why the limit is not one.
  2. Deploy the new secret everywhere the old one was, and let it run long enough that you are confident nothing is still using the old key. The dashboard shows each key's last use, which is what confirms it.
  3. Revoke the old key. It stops authenticating on its next use.

Revoking is immediate and permanent. A revoked key cannot be reinstated; create a new one instead.

Keeping the secret

  • An environment variable or a secrets manager — never a file committed to version control. A key in a repository is a key in every clone of that repository, including the ones you no longer control.
  • Different keys for different environments, so revoking a compromised staging key does not take production down with it.
  • One key per project rather than one key shared across several, so usage is attributable and a revocation is contained.
  • Restrict a key to the targets it actually needs, and check its last-used date before revoking anything.

When authentication fails

A missing, malformed, unknown or revoked key is answered identically, with unauthorized and HTTP 401. Telling the four apart would tell somebody probing the API which of their guesses was closer to a real key.

A suspended project is also answered with unauthorized: the key itself may be intact, but nothing it belongs to is entitled to run. See Errors for the full table.