Skip to content

Authentication

Wallet lane (the iframe)

Every request under /v1/wallets/... carries two pieces of auth:

HeaderValue
X-Sigil-Publishable-KeyThe org’s pk_live_…
AuthorizationBearer <jwt> — the end-user token

The publishable key identifies the org. The JWT is either:

  • Sigil mode: minted by POST /v1/wallets/auth/email-otp/verify after the user completes the email OTP. HS256 with our internal secret.
  • OIDC mode: minted by your own provider; we validate against your JWKS via the autodiscovery URL configured per-org.

Two endpoints are gated by publishable key only because they exist to mint the JWT in the first place:

  • POST /v1/wallets/auth/email-otp/start
  • POST /v1/wallets/auth/email-otp/verify

Everything else under /v1/wallets/... requires both headers.

Server-to-server lane

GET /v1/s2s/wallets HTTP/1.1
Host: api.sigilkeys.com
Authorization: Bearer sk_live_xxx

Secret keys are revocable from the portal API keys tab. Rotate them the moment you suspect leakage.

Portal lane

The Kratos session cookie (ory_kratos_session) is set by the auth.sigilkeys.com server-side flows. The Go backend validates it on every request via Kratos whoami. There’s no app-level auth header.

The portal SPA never sees the cookie value — it’s HttpOnly.

CORS

The API is open to the configured allowed origins per org plus the fixed Sigil-owned origins (https://wallet.sigilkeys.com, https://platform.sigilkeys.com). Browsers from other origins will get the request blocked client-side; the server still returns the data correctly when CORS isn’t an issue (server-to-server).