Cariosan

API keys

How api_key, api_secret, and user JWTs differ — and where each one belongs.

4 min readUpdated May 14, 2026

Cariosan uses three different credential types. Mixing them up is the most common integration mistake — this page maps each to where it belongs.

The three credentials

CredentialPrefixLifetimeWhere it goes
api_keypk_live_… or pk_test_…Until workspace deletedServer-side env var; safe to log
api_secretsk_live_… or sk_test_…Until rotatedServer-side secret manager only; never in logs, frontend, or repos
User JWTeyJ…Default 24hIssued per end-user, passed to client SDKs

api_key (pk_*)

The public key. Safe to put in env vars, your CI configuration, and your docker-compose.yml.

Where you use it:

  • Server SDK constructor — your backend calling Cariosan's REST API to upsert users, create channels, send webhooks.
  • Cariosan Cloud dashboard — visible in the Overview page with copy-to-clipboard.
  • Headers — sent alongside api_secret as Authorization: Bearer <api_key>:<api_secret>.

Where it does NOT go:

  • Your frontend JavaScript bundle (use a user JWT instead).
  • A public Git repo (although disclosure is recoverable via rotation — see below).

api_secret (sk_*)

The signing secret. Treated like a database password.

Where you use it:

  • Server SDK constructor — paired with api_key.
  • Webhook signature verification (X-Cariosan-Signature HMAC uses this secret).

Where it does NOT go:

  • ANY frontend code.
  • Logs, error reports, or analytics events.
  • Cariosan Cloud's dashboard does not store the plaintext — once you close the modal showing it, the only way to retrieve it is to rotate.

One-time reveal

Cariosan Cloud shows the plaintext api_secret exactly once: right after workspace creation, and right after a manual rotation. We hash it server-side and discard the plaintext. Copy it to your secret manager immediately.

User JWTs

Short-lived tokens you issue from your backend, scoped to a single end-user.

Where you use them:

  • Client SDKs (@cariosan/client, @cariosan/react) on the browser / mobile.
  • The user JWT lets that ONE user read their messages and send new ones — they can't read other users' data.

How to issue:

  • Backend calls the Go SDK's IssueUserToken(userID) (or its TypeScript equivalent) with your api_key + api_secret.
  • Hand the JWT to your frontend through your existing auth flow (alongside your own session, typically).

JWTs default to 24h. Tune via CARIOS_JWT_TTL_HOURS if you self-host; on Cariosan Cloud the default is fixed at 24h.

Rotation

Rotation invalidates the current api_secret immediately. Any server using the old secret receives 401 until you redeploy with the new one.

Cariosan Cloud — dashboard rotation

  1. Open the workspace in dashboard.cariosan.com.
  2. Click Regenerate secret in the Overview page.
  3. The new api_secret displays once. Copy it.
  4. Update your secret manager. Redeploy your backend.

Self-host — CLI rotation

terminal
docker compose exec cariosan-server /cariosan workspace rotate-secret \
  --workspace-id ws_01J7KQR8...

Same one-time reveal applies.

Plan rotation around redeploy

The old secret stops working the moment rotation completes. If your backend is mid-deploy, requests using the old secret error during the window. Best practice: rotate immediately after you've already published the new secret to your runtime config.

Lost the secret?

If you no longer have the secret AND no way to recover from your own secret manager:

  • Cariosan Cloud — click Regenerate secret. The replacement is shown once.
  • Self-host — run /cariosan workspace rotate-secret.

There's no recovery path that returns the original. The hashed value on the server can't be reversed.

Test mode keys (pk_test_ / sk_test_)

Not implemented in Phase A. Today every workspace's keys are live (pk_live_ / sk_live_). Test-mode workspaces — separate ID space, no quota counting against billing — ship with the paid tier.

Next steps

Was this page helpful?

On this page