Authentication
The three ways to authenticate against TRUE: a wallet session for end users, a true_sk MCP key for your own backend, and OAuth 2.1 for multi-user AI clients.
Three credentials, three jobs
TRUE issues three kinds of credential. They are not interchangeable, and the fastest way to lose a day is to send the wrong one.
| Credential | Looks like | For |
|---|---|---|
| Wallet session | a JWT, issued by Dynamic | An end user signed into the TRUE app on web or mobile |
| MCP key | true_sk_… | Your own backend, or one AI client acting as you |
| OAuth 2.1 grant | an access token | A product that serves many TRUE users, each acting as themselves |
| Trade key | apikey_… | Programmatic trading against the TRUE DEX sequencer |
The trade key is a different animal and lives in its own section: see Keys and Access. Everything below covers the first three.
Wallet session (Dynamic)
End users sign in with email, a social login, or by signing a message with a Solana wallet. Dynamic verifies it and issues a JWT bound to the user. TRUE is non-custodial: that session lets the app read your account and ask you to sign, it does not let TRUE move your funds.
Present it as Authorization: Bearer <jwt>. Wallet sessions are for the app, not for server-to-server integrations, because they expire on a user-facing cadence and are refreshed by the client SDK.
MCP keys
A TRUE user mints an MCP key from MCP & API → Setup in the app. It is a single secret that identifies both you and your TRUE account.
POST https://app.truefinance.ai/api/v1/mcp/keys GET https://app.truefinance.ai/api/v1/mcp/keys DELETE https://app.truefinance.ai/api/v1/mcp/keys/{id} GET https://app.truefinance.ai/api/v1/mcp/keys/validate - Prefix:
true_sk_followed by 64 hex characters. - Shown once. TRUE stores a SHA-256 hash and a short preview. Nobody at TRUE can read your key back to you, including support.
- Expiry: 90 days by default, 365 maximum. Pass
expiresInDaysat creation. - Revocation is immediate: delete the key and the next request fails.
Send it as a bearer token against the MCP endpoint:
curl https://app.truefinance.ai/api/v1/mcp \
-H "Authorization: Bearer true_sk_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Per-key IP allowlist
Every key can be pinned to a set of IP addresses or CIDR ranges. A key used from outside its allowlist is refused regardless of whether the secret is correct, which is what makes a leaked key useless to whoever leaked it. Set it in the app next to the key; changes are confirmed by an emailed code. Tiers, limits and the headers we return are on Rate Limits.
OAuth 2.1
Use OAuth when your product serves many TRUE users and each tool call should run as that user, inheriting their account rather than yours. The server publishes standard metadata, so most clients configure themselves from the discovery document alone.
GET https://app.truefinance.ai/.well-known/oauth-authorization-server | Endpoint | URL |
|---|---|
| Authorization | https://app.truefinance.ai/oauth/authorize |
| Token | https://app.truefinance.ai/oauth/token |
| Dynamic client registration | https://app.truefinance.ai/oauth/register |
| Revocation | https://app.truefinance.ai/oauth/revoke |
| User info | https://app.truefinance.ai/oauth/userinfo |
These live at the site root, not under /api. A request to /api/v1/oauth/authorize will 404.
Scopes
Four scopes, and the app shows the user exactly which ones an app is asking for before they approve.
| Scope | Allows |
|---|---|
read:chat | Read the user’s TRUE chat context |
read:points | Read their points balance and history |
read:market | Market data, prices, asset search |
trade:execute | Propose an order. Nothing executes on this scope alone. |
A client holding trade:execute can stage an order and nothing more. Every trade is approved by the user inside an authenticated TRUE session, and leveraged orders never auto-approve. The scope buys an assistant the right to ask, not the right to act.
Flow
Authorization code with PKCE. S256 is the only challenge method, code the only response type, and refresh tokens are supported. Public clients register with none for token endpoint auth; confidential clients may use client_secret_post or client_secret_basic.
https://app.truefinance.ai/oauth/authorize
?response_type=code
&client_id=<your client id>
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&code_challenge=<S256 challenge>
&code_challenge_method=S256
&scope=read:market%20read:points
&state=<opaque>
- Never commit a key to a repo, private ones included, and never ship one in a client-side bundle. Proxy through your own backend.
- Pin an IP allowlist. It is the only control that still protects you after the secret has leaked.
- Ask for the narrowest scope that works. A grant without
trade:executecannot stage a trade even if it is stolen. - On compromise, revoke first, then rotate your consumers. Revocation is instant and does not wait for the key to expire.
- TRUE never asks for raw key material. Any “verify your key” link asking you to paste one is a phishing attempt.
Which one do I want
- Wallet session — you are rendering the TRUE app or an embed and the user holds the wallet.
- MCP key — your backend, or your own Claude/Cursor setup, talking to TRUE as you.
- OAuth — your product talking to TRUE on behalf of each of its own users.
- Trade key — a bot placing signed orders on the DEX. Different credential, different host, own page.
Validating a key without making a tool call
curl https://app.truefinance.ai/api/v1/mcp/keys/validate \
-H "Authorization: Bearer true_sk_..."Returns the key’s owner and state. Useful as a health check in your deploy pipeline, so a rotated key fails at deploy time rather than at 3am.
Failure modes worth knowing
- 401 with a JWT-shaped error on a key you just made. You sent a trade key where an MCP key belongs, or the reverse. The prefixes are
true_sk_andapikey_and they route to different services. - 403
ip_not_allowed. The key has an allowlist and your egress address is not in it. Mobile networks and VPNs change address; the app shows the address we see for you. - 429. Read
RateLimit-RemainingandRetry-Afterrather than retrying blind. See Rate Limits. - 404 on an OAuth endpoint. You prefixed it with
/api. They live at the root.
See also
- MCP — what these credentials unlock.
- Trading keys — the separate
apikey_credential for the DEX. - Rate Limits — tiers, allowlists and the headers.