All Platform API requests require a valid JWT passed in a custom header. The API supports multiple authentication providers — your platform administrator configures which provider to use.
Multi-tenant integrations identify both the organisation and the environment a request belongs to using a single header value formatted as <org-id>:<env-id>.
Both halves are required, even if your organisation only has a single environment — Sumvin always resolves auth configuration per environment, so the env half pins the request to the correct provider credentials.A complete header looks like this:
If the value is present but not formatted as two non-empty halves separated by a single colon, the API responds with 401 Unauthorized and error code USR-401-002:
{ "type": "https://api.sumvin.com/errors/usr-401-002", "title": "Invalid Org ID Format", "status": 401, "detail": "x-juno-orgid must be formatted as '<org-id>:<env-id>'.", "instance": "/v0/user/me", "error_code": "USR-401-002"}
Single-tenant integrations can omit the header entirely; the API resolves the JWT against the default provider in that case.
Embedded wallets and email/SMS/social login, with MPC key management
SIWE
Sign-In With Ethereum (EIP-4361) — direct wallet-based auth
Which providers are active is configured per environment in the SIS Dashboard. Your platform is configured with one or more providers — refer to your provider’s SDK documentation for how to obtain JWTs.
Sumvin verifies the JWT signature against the configured provider’s JWKS endpoint (or pinned verification key) and reads the following standard claims from the payload:
Claim
Required
Description
sub
Yes
User’s unique identifier from the auth provider
exp
Yes
Token expiration time (Unix timestamp, seconds)
iss
Yes
Issuer URL — used to detect which provider signed the token (e.g. privy.io, dynamicauth.com)
aud
Recommended
Audience — for Privy, this should be your App ID
A Privy identity token decoded payload looks roughly like this:
When your environment is configured in App ID only mode, Sumvin verifies Privy identity tokens. Identity tokens carry user claims (linked accounts, wallets, email) directly in the JWT — Privy access tokens do not, and will fail verification.
Privy identity token ≠ Sigil. The Privy identity token authenticates the end-user’s linked accounts (wallets, email, OAuth) to Privy’s system and is the credential Sumvin uses to establish a session. It tells the API who the user is, but carries no KYC or personhood verification. Sigil is Sumvin’s portable Proof of Personhood — a separate product layer provisioned after KYC passes and onboarding completes. A valid Privy identity token is a prerequisite for reaching the Sumvin API, but it does not constitute a Sigil. See the Juno Privy authentication guide for token mechanics.
Privy exposes identity tokens through the useIdentityToken React hook:
import { useIdentityToken } from "@privy-io/react-auth";export function useSumvinAuthHeaders() { const { identityToken } = useIdentityToken(); if (!identityToken) { return null; } return { "x-juno-jwt": identityToken, "x-juno-orgid": "org-...:env-...", };}
getIdentityToken() from the headless SDK returns the same value if you’re not using React. See the Privy documentation for setup details — in the Privy console, identity tokens must be enabled under User management → Authentication → Advanced → Return user data in an identity token.
Privy identity tokens follow the JWT lifetime configured in the Privy console (typically one hour for identity tokens; access tokens are shorter-lived). The token Sumvin verifies must be fresh on every request.
useIdentityToken re-fetches when the underlying session refreshes — read identityToken per request rather than caching the value.
For long-lived sessions (dashboards, background tasks), refresh proactively before exp to avoid silent 401s. Privy’s React SDK refreshes in the background as long as usePrivy is mounted.
Once exp has passed, Sumvin returns 401 with USR-401-001. Treat this as a signal to refresh and retry once.
The API resolves user identity from the JWT — you never pass user_id in URLs or request bodies. Endpoints scoped to “the current user” derive identity from the token rather than a path parameter. For example:GET /v0/user/me — Fetch the current user.POST /v0/user/me/onboarding/steps — Submit onboarding for the current user.On first request, if no user exists for the JWT’s sub claim, you must create one:
This surface is how you query — Sumvin’s portable, KYC-verified Proof of Personhood. On the wire, Sigil is the SRI identity system: the SRI identifiers, identity tokens, scopes, and KYC verification status you read through the endpoints below.The Sumvin Identity Service (SIS) uses API key authentication via the Authorization: Bearer header.
SIS keys are scoped at mint time. Each key carries an explicit set of scopes drawn from a dotted-namespace catalogue. A key’s partition — public-safe vs server-only — is derived from the namespace prefix of its scopes.
The sis and rpc namespaces sit in two distinct partitions. A key cannot span both.
Partition
Namespaces
Where to use
Public-safe?
Server
sis.*
Server-side only — your backend calling sis.sumvin.com
No — never embed in browsers, mobile bundles, or anything user-controlled
Public
rpc.*
Client-side — browsers, mobile apps, server-side proxies
Yes — designed to be exposed in client bundles
Partition is fixed post-mint. A key’s partition is determined by the namespace of its scopes at mint time and cannot be changed. To move a key between partitions, revoke and mint a new one. Within a partition, scopes are mutable (a future PATCH endpoint will let you grant additional same-partition scopes — not yet shipped).The mint response surfaces partition ("public" or "server") and the verbatim scopes array, so dashboards and ops tooling can render badges without a second round-trip.
The request body takes a scopes array. The partition is derived from the namespaces of the scopes you request — mixing sis.* and rpc.* in the same request is rejected with 422 SIS-422-006.Minting keys is a dashboard-admin operation on the SIS host (sis.sumvin.com), authenticated with your dashboard session token via the Authorization: Bearer header. The organisation is taken from the <org_id> path segment.
The plaintext key is returned once — store it immediately. Subsequent reads do not return the plaintext.Public-partition keys carry both rpc_endpoint (the RPC base URL the key authenticates against) and rpc_docs (the RPC method reference) HAL links. Server-partition keys carry neither.
The scopes array is empty, contains an unknown scope, or mixes sis.* and rpc.* in one request
422
(FastAPI default)
scopes field missing entirely from the body, or env_id missing
Pre-existing partner keys are migrated to the dotted scope catalogue automatically. Their partition is preserved (a key with the legacy lookup scope ends up in the server partition with sis.lookup); they cannot be elevated across partitions via mutation — the only path between partitions is re-mint.
For more on the SIS API and identity concepts, see Identity & PINTs.