Authentication
API keys, what each key type may do, and how test and live modes are separated.
Borga authenticates server-to-server requests with API keys sent as a bearer token:
Authorization: Bearer sk_test_…Keys are created and revoked in the dashboard under Developers. A key belongs to one merchant and one mode, so the key alone tells Borga who you are and whether you are in test or live mode. There is no merchant header to send.
AI assistants do not use API keys. They connect through the MCP server with OAuth access tokens bound to one merchant, one mode and the permissions a person granted; see OAuth for third-party clients.
Key types
| Prefix | Type | Where it lives | What it can do |
|---|---|---|---|
sk_test_, sk_live_ | Secret | Your servers only | Everything in the API for its mode |
pk_test_, pk_live_ | Publishable | Browser code | Create embedded payment sessions from an allowed origin. Nothing else. |
Secret keys are shown once at creation and stored as a bcrypt hash. Publishable keys are safe to ship in front-end code: a leaked publishable key can only start a checkout for your own merchant from a page on one of its allowed origins, for an amount your server never sees. Publishable keys carry an allowed_origins list you manage in the dashboard; localhost and 127.0.0.1 are always allowed for development.
Test and live mode
Every key is bound to a mode. Objects created with a test key exist only in test mode and can never be seen or charged with a live key, and vice versa. A live key of either type works only once your merchant has been approved for live mode; until then the API returns live_mode_not_enabled. See Go live.
Errors you will meet first
| Code | HTTP | Cause |
|---|---|---|
missing_api_key | 401 | No Authorization: Bearer header |
invalid_api_key | 401 | Malformed, unknown or revoked key |
live_mode_not_enabled | 401 | Live key used before live mode was approved |
publishable_key_not_allowed | 403 | Publishable key used for a secret-only operation |
Dashboard access is separate
The dashboard signs in with Kenni (Icelandic electronic ID) and uses its own session tokens. Configuration that lives in the dashboard, such as API keys, webhook endpoints, allowed redirect domains, your accounting connection and subscription retry settings, is not exposed to API keys. If you call one of those endpoints with an API key you get wrong_auth_method. An assistant connected through the MCP server can reach some of them, within the permissions it was granted; minting API keys and connecting an accounting provider stay in the dashboard.
Using the SDK
The Node SDK reads the key once and adds the header to every request:
import { Borga } from "@borga/node";
const borga = new Borga({ apiKey: process.env.BORGA_SECRET_KEY! });It refuses publishable keys, since they cannot do anything useful from a server.