32 — Developer

Authentication

The Finscale API authenticates every request with a Bearer secret key over TLS. Secret keys live on your servers only; publishable keys handle the one browser-facing job — initializing checkout in the browser.

Secret keys

Each account has one secret key per mode:

KeyModeMoves
sk_test_51FinscaleDemo…TestTest money only. Safe to use from day one.
sk_live_••••••••••••LiveReal money. Issued after account activation; shown once, then redacted everywhere.

Pass the key in the Authorization header of every request:

Authenticated request
curl https://api.finscale.dev/v1/payments/pay_8Q2mX4nT1cVb \
  -H "Authorization: Bearer sk_test_51FinscaleDemo…"

The mode of the key selects the mode of the data: a sk_test_ key sees only test payments and returns "livemode": false on every object. There is no header or flag to cross modes.

A missing or invalid key returns 401 with an authentication_error:

401 Unauthorized
{
  "error": {
    "type": "authentication_error",
    "code": "api_key_invalid",
    "message": "No valid API key provided. Pass your secret key as Authorization: Bearer sk_test_…",
    "request_id": "req_7Hf3kQd2"
  }
}
TLS only

The API is served exclusively over HTTPS. Plain-HTTP requests are refused at the edge — the key never gets a chance to leak in transit.

Never client-side

A secret key is full control of your account: it can create payments, issue refunds, and read every customer record. Treat it like a database password.

  • Never ship it in browser JavaScript, mobile app binaries, or desktop clients — anything a customer can decompile or inspect.
  • Never commit it to a repository, even a private one. Load it from your secret manager or environment at runtime.
  • Never log it. Redact Authorization headers in request logging and error trackers.

If a key does leak, rotate it immediately — and remember test keys deserve the same hygiene, since they expose real customer emails and order references from your test data.

Key rotation

Rotate keys from the Dashboard (Developers → API keys → Roll key). Rotation is zero-downtime:

  1. Roll the key

    Rolling issues a new secret key immediately. You choose a grace period for the old one: revoke now, in 1 hour, in 24 hours, or in 7 days.

  2. Deploy the new key

    Both keys authenticate during the grace period, so you deploy the replacement at your own pace — no dropped requests.

  3. Old key expires

    When the grace period ends, the old key returns 401 authentication_error. The Dashboard shows the last time each key was used, so you can confirm nothing still depends on it before it dies.

Rotate on suspicion, not on proof

If a key may have leaked — a pasted log, a screen share, a departed contractor — roll it with revoke now. A minute of forced redeploy beats an attacker with write access to your payments.

Restricted keys

Today the API has two key kinds: secret and publishable. Scoped keys with per-resource permissions — a read-only key for a reconciliation worker, a refund-only key for support tooling — are on the roadmap and will appear in Developers → API keys when available. Until then, isolate services operationally: one deployment per service, secrets injected per environment, and the Dashboard's per-key usage log as your audit trail.

Publishable keys

Publishable keys (pk_test_51FinscaleDemo… / pk_live_…) are the only keys that belong in a browser. They can do exactly one thing: initialize Finscale's browser-side checkout components for a payment your server already created.

Server creates the payment, browser opens it
# Server side — secret key creates the payment
curl https://api.finscale.dev/v1/payments \
  -H "Authorization: Bearer sk_test_51FinscaleDemo…" \
  -H "Idempotency-Key: idem_ord_9f21_0716" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 4900,
    "currency": "EUR",
    "payment_method": "ideal",
    "reference": "ord_9f21_0716",
    "return_url": "https://shop.example.com/checkout/return"
  }'
# → next_action.url: "https://pay.finscale.dev/r/8Q2mX4nT"

# Browser side — send the customer to next_action.url.
# The pk_ key initializes embedded checkout fields; it cannot read or move anything.

Publishable keys can't read payments, can't refund, can't list anything. Exposing one is harmless by design — but card data still never touches your servers: the hosted checkout page collects it directly, built to PCI DSS Level 1 standards. See Security.

Key prefixes at a glance

PrefixKindLives
sk_test_ / sk_live_Secret key — full API accessServer only
pk_test_ / pk_live_Publishable key — hosted checkout initBrowser-safe
whsec_Webhook signing secret — verifies webhooksServer only