Authentication
Deltalytix is its own OAuth 2.0 authorization server. Humans still sign in with Supabase; API tokens are minted and validated by Deltalytix.
Token formats
Tokens are opaque strings. Deltalytix stores only SHA-256 hashes.
| Kind | Prefix | Lifetime |
|---|---|---|
| Access token | dltx_at_<48 hex chars> | 3600 seconds |
| Refresh token | dltx_rt_<48 hex chars> | 30 days (rotated on use) |
| Personal access token (PAT) | dltx_pat_<48 hex chars> | No expiry until revoked |
| Client ID | dltx_app_<24 hex chars> | — |
| Client secret | dltx_secret_<48 hex chars> | Shown once at creation |
Scopes
Request only the scopes your integration needs. Space-separate them in OAuth scope parameters.
| Scope | Access |
|---|---|
profile:read | Read the authenticated user profile |
trades:read | List trades |
trades:write | Create trades |
accounts:read | List accounts and related metrics |
connections:read | List broker connections |
connections:write | Create connections and trigger sync |
imports:write | Upload import files |
metrics:read | Read summary, equity, and account metrics |
Personal access tokens
PATs are ideal for scripts and private tools. Create and revoke them from the dashboard developer settings, choosing the scopes you need. The token value is shown once.
curl https://www.deltalytix.app/api/v1/me \
-H "Authorization: Bearer dltx_pat_YOUR_TOKEN"OAuth 2.0 authorization code + PKCE
1. Authorize
Send the user to the consent page (HTML). Unauthenticated users are redirected to /authentication?next=….
GET /oauth/authorize
?client_id=dltx_app_…
&redirect_uri=https%3A%2F%2Fyour-app.example%2Fcallback
&response_type=code
&scope=profile%3Aread%20trades%3Aread
&state=csrf-token
&code_challenge=BASE64URL_SHA256_OF_VERIFIER
&code_challenge_method=S256| Query | Required | Notes |
|---|---|---|
client_id | Yes | Registered OAuth app |
redirect_uri | Yes | Must exactly match a registered URI |
response_type | Yes | Must be code |
scope | Yes | Space-separated scopes |
state | Recommended | CSRF protection; echoed on redirect |
code_challenge | Recommended | PKCE S256 challenge |
code_challenge_method | With challenge | Must be S256 |
On approve, Deltalytix issues a single-use authorization code (10 minute TTL) and redirects:
https://your-app.example/callback?code=…&state=…On deny:
https://your-app.example/callback?error=access_denied&state=…2. Exchange the code for tokens
POST /api/oauth/token accepts form-urlencoded or JSON.
curl -X POST https://www.deltalytix.app/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://your-app.example/callback" \
-d "client_id=dltx_app_…" \
-d "code_verifier=PKCE_VERIFIER"Confidential clients may send client_secret instead of (or in addition to) PKCE, depending on how the app was registered.
Successful response:
{
"access_token": "dltx_at_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "dltx_rt_…",
"scope": "profile:read trades:read"
}OAuth errors follow RFC 6749:
{
"error": "invalid_grant",
"error_description": "Authorization code is invalid or expired"
}3. Call the API
curl https://www.deltalytix.app/api/v1/trades?limit=10 \
-H "Authorization: Bearer dltx_at_…"const res = await fetch("https://www.deltalytix.app/api/v1/trades?limit=10", {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});4. Refresh the access token
curl -X POST https://www.deltalytix.app/api/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "dltx_rt_…",
"client_id": "dltx_app_…",
"client_secret": "dltx_secret_…"
}'Refresh tokens rotate on use. Store the new refresh_token from each successful response.
Public clients that obtained tokens via PKCE may refresh without a client secret when that was how the original token was issued.
5. Revoke a token
curl -X POST https://www.deltalytix.app/api/oauth/revoke \
-H "Content-Type: application/json" \
-d '{
"token": "dltx_at_…",
"client_id": "dltx_app_…",
"client_secret": "dltx_secret_…"
}'Revocation always returns 200, whether or not the token was found.
Resource-server failures
Missing or invalid Bearer tokens return 401:
{
"error": "unauthorized",
"message": "…"
}with a WWW-Authenticate header pointing at protected-resource metadata.
Valid tokens without the required scope return 403:
{
"error": "insufficient_scope",
"message": "…"
}Managing apps and tokens
In the dashboard developer settings you can:
- Create OAuth apps (name, redirect URIs, allowed scopes) —
client_idis always visible;client_secretis shown once - Create and revoke personal access tokens with chosen scopes — the PAT value is shown once