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

PrefixTypeWhere it livesWhat it can do
sk_test_, sk_live_SecretYour servers onlyEverything in the API for its mode
pk_test_, pk_live_PublishableBrowser codeCreate 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

CodeHTTPCause
missing_api_key401No Authorization: Bearer header
invalid_api_key401Malformed, unknown or revoked key
live_mode_not_enabled401Live key used before live mode was approved
publishable_key_not_allowed403Publishable 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.