Authentication
A Sevren account is an Ethereum wallet: you sign in by signing a message with it, which costs no gas. Each sign-in creates a session token, and that token is also your API key.
Credentials
Send a credential as a bearer token in the Authorization header.
Authorization: Bearer sk-sv-user-…| Credential | Looks like | Used for |
|---|---|---|
| None | No header | GET /v1/catalog and GET /v1/models (open models only). |
| Session token | sk-sv-user-… | The account API and every model. Paid models are charged to the account: holder free tokens on the model first (the free try, then the plan's tokens of the day), then credit. |
| Account key | sk-sv-acct-… | A key the operator issues for a credit account. Not used by web app accounts. |
Session tokens
A wallet sign-in answers with a token and its expiresAt. The same token authorizes the account API under https://api.example.com/account and model requests under https://api.example.com/v1.
- Lifetime: 14 days from sign-in. Using the token does not extend it; sign in again for a new one.
- Limit: at most 20 live sessions per account. A 21st sign-in ends the oldest session.
- Revocation:
POST /account/logoutends the session it is called with. - Storage: Sevren keeps only a hash of each token and cannot show it again. Nothing is set in cookies, so there is no cross-site request forgery surface.
- After expiry: the account API answers
401 invalid_sessionand the model API answers401 invalid_api_key.
The token on the account page of the web app belongs to that browser session, and signing out there revokes it. For a script or server, sign in once more in another browser window, copy that session's token from the account page and close the window without signing out: each sign-in is a separate session. Keep the token in an environment variable or a secret store, never in source code or URLs.
# Check the token
curl https://api.example.com/account/me -H "Authorization: Bearer $SEVREN_API_KEY"
# Revoke the token
curl -X POST https://api.example.com/account/logout -H "Authorization: Bearer $SEVREN_API_KEY"Wallet sign-in
Any Ethereum wallet that supports personal_sign can sign in on Robinhood Chain (chain id 4663). Ordinary accounts and contract wallets that implement ERC-1271, such as Safe, Coinbase Smart Wallet and Argent, are verified. A contract wallet that is not deployed yet (an ERC-6492 signature) cannot sign in. The first sign-in with a wallet creates its account.
On the sign-in page, Privy's wallet connector lists wallets and connects the one you pick: a browser wallet, or a mobile wallet through WalletConnect. Privy only connects the wallet. Your wallet signs the message, and the Sevren auth service verifies it; no Privy login or account is involved, and Sevren's servers receive nothing from Privy.
Wallet sign-in is built for the Sevren web app: the domain and URI in the signed message must be an origin the operator allows, which is https://app.example.com. To use a wallet account from code, sign in on the web app and use its session token. The rest of this section describes the flow so you can check exactly what your wallet is asked to sign.
GET https://auth.example.com/auth/wallet/config
-> {"chainId":4663,"statement":"…","resourcePrefix":"urn:sevren:wallet:","maxMessageAgeSeconds":300,"plans":{…}}
POST https://auth.example.com/auth/siwe/nonce
-> {"nonce":"…","expiresAt":"…"}
personal_sign(message, address) # in the wallet
POST https://auth.example.com/auth/wallet/verify {"message":"…","signature":"0x…"}
-> {"assertion":"svw1.…","expiresAt":"…","purpose":"login","plan":{…}|null,"holdingBps":0}
POST https://api.example.com/account/login/wallet {"assertion":"svw1.…"}
-> 200 {"token":"sk-sv-user-…","expiresAt":"…","user":{…}}
-> 201 {"token":"sk-sv-user-…","expiresAt":"…","created":true,"user":{…}} # first sign-in: a new accountThe signed message
The message follows EIP-4361 (Sign-In with Ethereum). The verifier accepts exactly this layout:
app.example.com wants you to sign in with your Ethereum account:
<your EIP-55 checksummed address>
<statement from GET /auth/wallet/config>
URI: https://app.example.com
Version: 1
Chain ID: 4663
Nonce: <nonce from POST /auth/siwe/nonce>
Issued At: 2026-10-09T12:00:00.000Z
Resources:
- urn:sevren:wallet:login- Line endings are LF only, with no trailing newline.
- The address is EIP-55 checksummed.
- The first line names the page host. Without a scheme the verifier reads
https; theURIline must be on the same origin. - The statement is exactly the
statementfromGET /auth/wallet/config, andChain IDis itschainId. Issued Atmust be no older thanmaxMessageAgeSeconds, and the nonce works once.- There is exactly one resource,
urn:sevren:wallet:login. A message without it, or with anotherurn:sevren:wallet:resource, answers400 invalid_resource.
The assertion returned by /auth/wallet/verify is valid for 5 minutes and works once. It carries a keyed pseudonym of the address and the holder plan, never the address itself.
Who sees the address
The auth service at https://auth.example.com verifies the signature and reads the wallet's share of the Sevren token supply at both the finalized and the latest block, which makes a flash loan useless for reaching a plan. The account service at https://api.example.com only receives the pseudonym and the plan — your address stays out of your account. Privy's wallet connector and, for mobile wallets, WalletConnect may see the address too; see Privacy.
Token-gated models
A model with access token_gated or nft_gated also needs an entitlement from the gate service in the X-Sevren-Entitlement header, unless the operator granted it to an account. The live catalog on the Models page shows whether any model is gated and what its gate requires.
