Authentication

The Fluveo /v1 API authenticates with secret API keys, using the same schemes declared by the Stripe OpenAPI contract. Existing Stripe-style auth code works unchanged.

Secret keys

A secret key is a server-side credential. It comes in two environments:

Key prefixEnvironmentBase URL
sk_test_...Sandboxhttps://api.sandbox.fluveo.dev
sk_live_...Productionhttps://api.fluveo.dev

Responses carry a livemode boolean so you can confirm which environment a request hit. The MVP issues sandbox keys only (sk_test_...); sk_live_ keys ship with the production environment split.

Key lifecycle

Keys are managed from the dashboard API keys page (and the first one is shown when you create your merchant).

  • Issue — “Create secret key” mints a new sk_test_ and shows the full key exactly once. Fluveo stores only a SHA-256 hash; the plaintext is never logged and can never be re-displayed.
  • Hint — after the show-once screen, a key is listed by a hint that keeps its full type+mode prefix plus the last four characters, e.g. sk_test_…a1b2. The hint preserves enough to tell test from live at a glance, but not enough to reconstruct the key.
  • Revoke — revoking a key is immediate and permanent; a revoked key is rejected on /v1. Revoked keys stay listed (with their hint and last-used time) for your audit trail. Propagation: a just-revoked key may keep working for up to 60 seconds while a cached resolution expires. Treat 60s as the worst-case window when rotating after a suspected leak.
  • Recover a lost key — there is no “reveal”. If you lose a key, create a new one and revoke the old one.

The two schemes

The /v1 API accepts either scheme. They are equivalent — pick whichever fits your HTTP client.

SchemeHow
HTTP Basic Authsecret key as the username, empty password: -u sk_test_...:
Bearer AuthAuthorization: Bearer sk_test_...

Docs and runnable examples prefer Basic Auth because it is the canonical curl form. Note the trailing colon in -u sk_test_...: — it sets an empty password so curl doesn’t prompt for one.

$# Basic Auth (canonical)
$curl https://api.sandbox.fluveo.dev/v1/payment_intents \
> -u sk_test_...: \
> -d amount=4242 -d currency=usd
$
$# Bearer Auth (equivalent)
$curl https://api.sandbox.fluveo.dev/v1/payment_intents \
> -H "Authorization: Bearer sk_test_..." \
> -d amount=4242 -d currency=usd

Secret keys vs. publishable keys

Publishable keys (pk_test_..., pk_live_...) are browser-side keys. They pair with a PaymentIntent’s client_secret so the customer’s browser can complete authentication directly — they are not valid for secret-key server operations and will be rejected on /v1 write calls.

KeySideUsed for
sk_test_ / sk_live_ServerAuthenticating /v1 API requests
pk_test_ / pk_live_BrowserClient-side confirmation with client_secret

The launch /v1 surface does not accept an api-key header — secret-key auth is the only supported scheme.

Keeping keys safe

  • Never expose a secret key in browser code, mobile apps, or a public repository. Anyone with sk_live_... can move real money. Use the publishable key + client_secret for anything client-side.
  • Use sandbox keys (sk_test_) everywhere except production. They run against the sandbox and can’t touch live funds.
  • Store keys in a secrets manager / environment variable, not in source.
  • Rotate a key from the dashboard if it may have leaked: create a new key, move your integration over, then revoke the old one. Revocation takes effect within 60 seconds (see Key lifecycle).

Authentication errors

A missing, invalid, or revoked key returns HTTP 401 with an authentication_error. The message never confirms whether a key once existed:

1{
2 "error": {
3 "type": "authentication_error",
4 "message": "Invalid API Key provided."
5 }
6}

If Fluveo cannot verify your key because key resolution is temporarily unavailable, you still get a 401 — but with a generic message that does not claim your key is invalid. Retry with backoff; do not rotate the key on this:

1{
2 "error": {
3 "type": "authentication_error",
4 "message": "We could not authenticate the request. Please try again shortly."
5 }
6}

See Errors for the full error envelope and every error type.