Authentication

Every request is authenticated with an API key, sent as a bearer token in the Authorization header:

Authorization: Bearer sk_live_2f6b0e4a1f9e2b1d5c7a0e3f11...

A request with a missing or invalid key is rejected with 401 authentication_error (see Errors). A secret key can move money, so treat it like a password. Keep it on your server, out of source control, and never ship it in a browser or mobile app.

Two kinds of key

Each account has a secret key and a publishable key.

Key Prefix Use it for
Secret sk_live_…, sk_test_… Server-side requests. It has full access to your account.
Publishable pk_live_…, pk_test_… Identifying your account in contexts where a secret would be unsafe. It cannot authorize writes.

You can view, copy, and roll keys in the dashboard under Settings, API keys. Rolling a key issues a new secret and stops the old one immediately, so update your servers before you roll in production.

Live and test

The environment is carried in the key itself. A live key reads and writes real data; a test key works against a separate test environment with the same endpoints and behavior. There is no separate host to configure. The key decides which data you touch, which makes it easy to run the same code against test and live.

Working inside a program

Most resources belong to a program, an isolated book of accounts. For those endpoints, name the program in the program_id header:

program_id: prog_1U09GGBWE4mVGRnIL6GmVmeZ

Account, transaction, hold, and reconciliation endpoints require it. Account-wide endpoints (programs, webhooks, and events) do not, because they are not tied to a single set of books.

Headers at a glance

Header When Purpose
Authorization Always Bearer <secret_key>
Content-Type On writes application/json
program_id Program-scoped endpoints The program the request runs against
idempotency_key Recommended on writes Retry safely without duplicating. See Idempotency.
Authentication - Ledgr | Padle